当我导入我构建的模块时,我收到了这个与 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
这实际上意味着什么?为什么会出现此错误?
原文由 kilojoules 发布,翻译遵循 CC BY-SA 4.0 许可协议
描述
该问题是由混合使用
libc++
libstdc++
的对象引起的。In our case, the library
myMod.so
(compiled withlibstdc++
) needboost-python
that compiled withlibstdc++
(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++ 库。 When astd::string
that has been created byFoo
will be passed toBar
,Bar
will think that this is an instance of its c++图书馆的std::string
然后可能会发生坏事(它们是完全不同的对象)。注意:在某些情况下,同一 API 的两个或多个不同版本在程序的完全不同部分中不会出现问题。如果他们在他们之间传递这个 API 的对象,就会有问题。但是,检查可能非常困难,尤其是当他们仅将 API 对象作为另一个对象的成员传递时。此外,库的初始化函数可以做不应该发生两次的事情。另一个版本可能会再次执行这些操作。
如何解决?
您始终可以重新编译您的库并使它们相互匹配。
您可以将
boost-python
作为静态库链接到您的库。然后,它几乎可以在每台计算机上运行(即使是没有安装boost-python
的计算机)。 在这里 查看更多信息。概括
myMod.so
需要另一个版本的boost-python
,它是用特定的 c++ 库编译的。因此,它不适用于任何其他版本。