“Symbol not found/Expected in:flat namespace”实际上是什么意思?

2024-06-17 18:57:45 发布

您现在位置:Python中文网/ 问答频道 /正文

当我导入我构建的模块时,会出现与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

这到底是什么意思?为什么会出现这个错误?


Tags: 模块inmoststringso错误linecall
3条回答

找不到符号表示找不到声明函数或变量的定义。使用程序编译共享对象的头文件时,链接器会将已声明函数和对象的符号添加到已编译程序中。当您的程序被操作系统的加载程序加载时,符号被解析,以便加载它们的定义。只有在这个时候,如果缺少实现,加载程序才会抱怨它找不到定义,因为可能无法解析库的实际路径,或者库本身没有使用函数或对象的定义所在的实现/源文件进行编译。在linux杂志http://www.linuxjournal.com/article/6463上有一篇关于这方面的好文章。

说明

这个问题是由混合使用libc++编译的对象和使用libstdc++编译的对象引起的。

在我们的例子中,库myMod.so(用libstdc++编译)需要boost-pythonlibstdc++编译(从现在起boost-python-libstdc++)。当boost-pythonboost-python-libstdc++时,它将工作正常。否则-在它的boost-python已经用libc++编译过的计算机(或另一个c++库)上,它将在加载和运行它时遇到问题。

在我们的例子中,发生这种情况的原因是开发人员故意更改了所有符号的名称,以防止您(并保护您)混合来自他们库的代码和来自不同库的代码:myMod.so需要一个从类型中获取参数的函数。在libc++中,此类型的名称为std::__1::pair。因此,未找到此符号。

要理解为什么混合同一API的两个版本是不好的,请考虑以下情况:有两个库:FooBar。它们都有一个接受std::string并将其用于某些用途的函数,但是它们使用不同的c++库。当由Foo创建的std::string将被传递给Bar时,Bar将认为这是其c++库的std::string的一个实例,然后会发生不好的事情(它们是完全不同的对象)。

注意:在某些情况下,同一个API的两个或多个不同版本在程序的完全不同的部分不会有问题。如果它们将在它们之间传递此API的对象,就会出现问题。但是,检查这一点可能非常困难,特别是当它们仅作为另一个对象的成员传递API对象时。此外,库的初始化函数可以执行不应该发生两次的操作。另一个版本可能会再次执行这些操作。

怎么解决?

  • 您始终可以重新编译库并使它们彼此匹配。

  • 您可以将boost-python作为静态库链接到库。然后,它将在几乎每台计算机上工作(即使是没有安装boost-python的计算机)。查看有关here的详细信息。

小结

myMod.so需要另一个版本的boost-python,它是用特定的c++库编译的。因此,它不适用于任何其他版本。

我也遇到同样的问题。

Expected in: flat namespace

添加链接器标志可解决此问题

-lboost_python37

将动态库名称更改为安装在操作系统上的名称。

顺便说一下,我的操作系统是macOS High Sierra,我使用brew安装boost_python3

相关问题 更多 >