当我导入我构建的模块时,会出现与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
这到底是什么意思?为什么会出现这个错误?
找不到符号表示找不到声明函数或变量的定义。使用程序编译共享对象的头文件时,链接器会将已声明函数和对象的符号添加到已编译程序中。当您的程序被操作系统的加载程序加载时,符号被解析,以便加载它们的定义。只有在这个时候,如果缺少实现,加载程序才会抱怨它找不到定义,因为可能无法解析库的实际路径,或者库本身没有使用函数或对象的定义所在的实现/源文件进行编译。在linux杂志http://www.linuxjournal.com/article/6463上有一篇关于这方面的好文章。
说明
这个问题是由混合使用
libc++
编译的对象和使用libstdc++
编译的对象引起的。在我们的例子中,库
myMod.so
(用libstdc++
编译)需要boost-python
用libstdc++
编译(从现在起boost-python-libstdc++
)。当boost-python
是boost-python-libstdc++
时,它将工作正常。否则-在它的boost-python
已经用libc++
编译过的计算机(或另一个c++库)上,它将在加载和运行它时遇到问题。在我们的例子中,发生这种情况的原因是开发人员故意更改了所有符号的名称,以防止您(并保护您)混合来自他们库的代码和来自不同库的代码:
myMod.so
需要一个从类型中获取参数的函数。在libc++
中,此类型的名称为std::__1::pair
。因此,未找到此符号。要理解为什么混合同一API的两个版本是不好的,请考虑以下情况:有两个库:
Foo
和Bar
。它们都有一个接受std::string
并将其用于某些用途的函数,但是它们使用不同的c++库。当由Foo
创建的std::string
将被传递给Bar
时,Bar
将认为这是其c++库的std::string
的一个实例,然后会发生不好的事情(它们是完全不同的对象)。注意:在某些情况下,同一个API的两个或多个不同版本在程序的完全不同的部分不会有问题。如果它们将在它们之间传递此API的对象,就会出现问题。但是,检查这一点可能非常困难,特别是当它们仅作为另一个对象的成员传递API对象时。此外,库的初始化函数可以执行不应该发生两次的操作。另一个版本可能会再次执行这些操作。
怎么解决?
您始终可以重新编译库并使它们彼此匹配。
您可以将
boost-python
作为静态库链接到库。然后,它将在几乎每台计算机上工作(即使是没有安装boost-python
的计算机)。查看有关here的详细信息。小结
myMod.so
需要另一个版本的boost-python
,它是用特定的c++库编译的。因此,它不适用于任何其他版本。我也遇到同样的问题。
添加链接器标志可解决此问题
将动态库名称更改为安装在操作系统上的名称。
顺便说一下,我的操作系统是macOS High Sierra,我使用brew安装
boost_python3
。相关问题 更多 >
编程相关推荐