问题描述
当我导入一个我构建的模块时,我得到这个与 boost-python 相关的错误:
When I import a module I built, I get this boost-python related error:
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
这实际上意味着什么?为什么会出现这个错误?
What does this actually mean? Why was this error raised?
推荐答案
说明
问题是由使用 libc++
编译的对象和使用 libstdc++
编译的对象混合引起的.
Description
The problem was caused by mixing objects that compiled with libc++
and object that compiled with libstdc++
.
在我们的例子中,库 myMod.so
(用 libstdc++
编译)需要 boost-python
使用 libstdc++
(从现在开始boost-python-libstdc++
)编译.当 boost-python
为 boost-python-libstdc++
时,它会正常工作.否则 - 在它的 boost-python
用 libc++
(或其他 C++ 库)编译的计算机上,加载和运行它会出现问题.
In our case, the library myMod.so
(compiled with libstdc++
) need boost-python
that compiled with libstdc++
(boost-python-libstdc++
from now). When boost-python
is boost-python-libstdc++
, it will work fine. Otherwise - on computer that its boost-python
has compiled with libc++
(or another c++ library), it will have a problem loading and running it.
在我们的例子中,发生这种情况是因为 libc++
开发人员有意更改了他们所有符号的名称,以防止您(并拯救您)从他们的库中混合代码和来自不同的代码:myMod.so
需要一个从类型中获取参数的函数.在libc++
中,这个类型的名字是std::__1::pair
.因此,没有找到这个符号.
In our case, it happens because that libc++
developers intentionally changed the name of all of their symbols to prevent you (and save you) from mixing code from their library and code from a different one: myMod.so
need a function that take an argument from the type. In libc++
, this type's name is std::__1::pair
. Therefore, this symbol was not found.
要理解为什么混合使用相同 API 的两个版本是不好的,请考虑这种情况:有两个库:Foo
和 Bar
.他们都有一个接受 std::string
的函数,并将它用于某些事情,但他们使用不同的 C++ 库.当 Foo
创建的 std::string
传递给 Bar
时,Bar
会认为这是它的 C++ 库 std::string
的一个实例,然后可能会发生不好的事情(它们是完全不同的对象).
To understand why mixing two version of the same API is bad, consider this situation: There are two libraries: Foo
and Bar
. They both have a function that takes a std::string
and uses it for something but they use a different c++ library. When a std::string
that has been created by Foo
will be passed to Bar
, Bar
will think that this is an instance of its c++ library's std::string
and then bad things can happen (they are a completely different objects).
注意:在某些情况下,同一 API 的两个或多个不同版本在程序的完全不同的部分中是没有问题的.如果它们在它们之间传递这个 API 的对象,就会出现问题.但是,检查可能非常困难,尤其是当他们仅将 API 对象作为另一个对象的成员传递时.此外,库的初始化函数可以做不应发生两次的事情.另一个版本可能会再次做这些事情.
Note: In some cases, there would be no problem with two or more different versions of the same API in a completely different parts of a program. There will be a problem if they will pass this API's objects between them. However, checking that can be very hard, especially if they pass the API object only as a member of another object. Also, a library's initialization function can do things that should not happen twice. Another version may do these things again.
您可以随时重新编译库并使它们相互匹配.
You can always recompile your libraries and make them match each other.
您可以将 boost-python
作为静态库链接到您的库.然后,它几乎可以在每台计算机上运行(即使是没有安装 boost-python
的计算机).查看更多关于 此处.
You can link boost-python
to your library as a static library. Then, it will work on almost every computer (even one that doesn't has boost-python
installed). See more about that here.
myMod.so
需要另一个版本的 boost-python
,一个使用特定 C++ 库编译的版本.因此,它不适用于任何其他版本.
myMod.so
need another version of boost-python
, one that compiled with a specific c++ library. Therefore, It would not work with any another version.
这篇关于“Symbol not found/Expected in: flat namespace"是什么意思?其实是什么意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!