“符号未找到/期望:平面命名空间”实际上是什么意思?

时间:2016-01-26 03:29:00

标签: python c++ import namespaces importerror

当我导入我构建的模块时,我得到了与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

这究竟意味着什么?为什么会出现这个错误?

6 个答案:

答案 0 :(得分:16)

描述

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

在我们的案例中,库myMod.so(使用 libstdc++ 编译)需要使用 boost-python libstdc++ >(从现在起boost-python-libstdc++)。当boost-pythonboost-python-libstdc++时,它会正常工作。否则 - 在其boost-python已使用 libc++ (或其他c ++库)编译的计算机上,加载并运行它时会出现问题。

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

要理解为什么混合同一API的两个版本是不好的,请考虑以下情况:有两个库:FooBar。它们都有一个函数,它接受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 ++文件)。

从“找不到符号”后面的字符串中,您可以了解缺少的库。