当我导入我构建的模块时,我得到了与boost-python相关的错误:
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: dlopen(./myMod.so, 2): Symbol not found: __ZN5boost6python7objects15function_objectERKNS1_11py_functionERKSt4pairIPKNS0_6detail7keywordES9_E
Referenced from: ./myMod.so
Expected in: flat namespace
in ./myMod.so
这究竟意味着什么?为什么会出现这个错误?
答案 0 :(得分:16)
问题是由混合使用 libc++
编译的对象和使用 libstdc++
编译的对象引起的。
在我们的案例中,库myMod.so
(使用 libstdc++
编译)需要使用 boost-python
libstdc++ >(从现在起boost-python-libstdc++
)。当boost-python
为boost-python-libstdc++
时,它会正常工作。否则 - 在其boost-python
已使用 libc++
(或其他c ++库)编译的计算机上,加载并运行它时会出现问题。
在我们的情况下,发生这种情况是因为 libc++
开发人员故意更改了所有符号的名称,以防止您(并保存您)混合来自其库和代码的代码另一个:myMod.so
需要一个从类型中获取参数的函数。在libc++
中,此类型的名称为std::__1::pair
。因此,未找到此符号。
要理解为什么混合同一API的两个版本是不好的,请考虑以下情况:有两个库:Foo
和Bar
。它们都有一个函数,它接受std::string
并将它用于某些东西,但它们使用不同的c ++库。当std::string
创建的Foo
传递给Bar
时,Bar
会认为这是其c ++库的std::string
的实例,然后坏事可能发生(它们是完全不同的对象)。
注意:在某些情况下,在程序的完全不同的部分中,同一API的两个或更多不同版本没有问题。如果他们将在它们之间传递此API的对象,则会出现问题。但是,检查可能非常困难,特别是如果它们仅将API对象作为另一个对象的成员传递。此外,库的初始化函数可以执行不应发生两次的事情。另一个版本可能会再次执行这些操作。
您始终可以重新编译库并使它们相互匹配。
您可以将boost-python
链接到您的库作为静态库。然后,它几乎可以在每台计算机上运行(即使是没有安装boost-python
的计算机)。详细了解here。
myMod.so
需要另一个版本的boost-python
,一个用特定的c ++库编译的版本。因此,它不适用于任何其他版本。
答案 1 :(得分:3)
我遇到了同样的问题。
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
添加链接器标志可解决问题
Expected in: flat namespace
将动态库名称更改为操作系统上安装的名称。
顺便说一下,我的操作系统是macOS High Sierra,我使用brew安装-lboost_python37
。
答案 2 :(得分:1)
这是我学到的东西(osx):
如果这应该可行(即它可以在另一台计算机上运行),您可能会遇到clang / gcc问题。要对此进行调试,请在引发错误的.so文件上使用otool -l
,或使用可疑库(在我的示例中为boost-python dylib文件)并检查内容。 / System /文件夹中的任何内容都是使用clang构建的,应该使用gcc编译器安装在其他地方。切勿删除/ System文件夹中的任何内容。
答案 3 :(得分:1)
.so
个文件是动态库(所以=共享对象)。在Windows上,它们被称为.dll
(动态链接库)。它们包含已编译的代码,其中包含可用于链接它们的任何可执行文件的函数。
重要的是要注意那些.so
不是Python文件。它们可能是从C或C ++代码编译而来,包含可以在Python代码中使用的公共函数(参见Extending Python with C or C++上的文档)。
在你的情况下,你有一个腐败的.so
。尝试重新安装受影响的库或Python,或两者兼而有之。
答案 4 :(得分:1)
未找到符号表示未找到声明的函数或变量的定义。当使用您的程序编译共享对象的头文件时,链接器会将已声明函数和对象的符号添加到已编译的程序中。当您的程序由OS的加载程序加载时,符号将被解析,以便加载它们的定义。只是在这个时候,如果缺少实现,加载器会抱怨它无法找到定义,因为可能无法解析到库的实际路径,或者库本身没有用实现编译/ source文件,其中函数或对象的定义所在。在linux日志http://www.linuxjournal.com/article/6463上有一篇很好的文章。
答案 5 :(得分:1)
就我而言,使用Cython编译时,我只是无法导入所有必需的源文件(C ++文件)。
从“找不到符号”后面的字符串中,您可以了解缺少的库。