python 什么是“符号未找到/预期位置:扁平名称空间”实际上是什么意思?

0g0grzrc  于 2023-01-19  发布在  Python
关注(0)|答案(9)|浏览(104)

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

这实际上意味着什么?为什么会出现此错误?

iih3973s

iih3973s1#

描述

此问题是由于混合使用 * libc++ * 编译的对象和使用 * libstdc++ * 编译的对象而导致的。
在我们的示例中,库myMod.so(使用 * libstdc++ * 编译)需要使用 * libstdc++ * 编译的boost-pythonboost-python-libstdc++从现在开始)。当boost-pythonboost-python-libstdc++时,它将正常工作。否则-在其boost-python已使用 * libc++ * 编译的计算机上(或另一个c库),它将有一个问题,加载和运行它。
在我们的例子中,这是因为 * libc++ * 开发人员故意更改了他们所有符号的名称,以防止您(并保护您)将他们库中的代码与其他库中的代码混合在一起:myMod.so需要从类型中获取参数的函数。在libc++中,此类型的名称为std::__1::pair。因此,未找到此符号。
要理解为什么混合使用同一API的两个版本是不好的,请考虑以下情况:有两个库:FooBar。它们都有一个接受std::string并将其用于某些用途的函数,但它们使用不同的c
库。当由Foo创建的std::string将传递给Bar时,Bar会认为这是其c++库的std::string的示例,然后可能会发生不好的事情(它们是完全不同的对象)。

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

如何解决这个问题?

  • 您可以随时重新编译库并使它们相互匹配。
  • 你可以把boost-python作为静态库链接到你的库中。然后,它将在几乎每台计算机上工作(即使是没有安装boost-python的计算机)。在这里查看更多信息。

总结

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

km0tfn4u

km0tfn4u2#

在我的情况下,我收到:

ImportError: dlopen(/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/xmlsec.cpython-38-darwin.so, 0x0002): symbol not found in flat namespace '_xmlSecDSigNs'

背景:

M1 MacBook Pro笔记本电脑
我使用python virtualenv(使用pyenv)来使用python3.8(3.8.2)的早期版本,而我的系统本机安装了3.8.10。
当我在激活的3.8.2 virtualenv中时,我注意到dlopen()中的路径指向本机python安装中的包,而不是virtualenv安装。

解决方案:

在我的情况下,我根本不需要原生3. 8版本,所以我简单地删除了它,这就解决了问题。

c9qzyr3d

c9qzyr3d3#

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

wlwcrazw

wlwcrazw4#

我遇到了同样的问题。

Expected in: flat namespace

添加链接器标志可修复此问题

-lboost_python37

更改这动态库名称到这一个安装在这操作系统.
顺便说一句,我的操作系统是macOS高塞拉利昂和我使用brew安装boost_python3

8yparm6h

8yparm6h5#

在我的例子中,我只是在使用Cython编译时未能导入所有需要的源代码(c++文件)。
从“Symbol not found”后面的字符串中,您可以了解缺少哪个库。

wqnecbli

wqnecbli6#

以下是我学到的(osx):
如果这真的有用(即它在另一台计算机上工作),您可能遇到了clang/gcc问题。要调试此问题,请对引发错误的.so文件或可疑库使用otool -l(在我的示例中,它是一个boost-python dylib文件)并检查其内容。并且应该和gcc编译器一起安装在其他地方。永远不要删除/System文件夹中的任何内容。

wz8daaqr

wz8daaqr7#

.so文件是动态库(so =共享对象)。在Windows上,它们被称为.dll(动态链接库)。它们包含编译代码,其中包含可供链接它们的任何可执行文件使用的函数。
这里需要注意的是,这些.so不是Python文件,它们可能是从C或C++代码编译而来的,并且包含可以从Python代码中使用的公共函数(参见Extending Python with C or C++的文档)。
在您的情况下,您有一个损坏的.so。尝试重新安装受影响的库或Python,或两者都安装。

tyky79it

tyky79it8#

问题

我在将Puma作为Rails应用程序的一部分运行时遇到了同样的问题
加载错误:dlopen(/用户/卡/. rbenv/版本/2.7.6/库/ruby/gems/2.7.0/gems/puma-5.6.4/库/puma/puma_http11.bundle,0x0009):在平面命名空间"_ERR_load_crypto_strings"中未找到符号

  • /用户/卡/. rbenv/版本/2.7.6/库/ruby/gems/2.7.0/gems/puma-5.6.4/库/puma/puma_http11.bundle

溶液

只需重新安装puma gem gem install puma即可解决

ufj5ltwl

ufj5ltwl9#

我找到的解决方案之一是使用no-binary标志卸载并重新安装它,这会强制pip从源代码编译模块,而不是从预编译的wheel安装。

pip install --no-binary :all: <name-of-module>

在此处找到此解决方案

相关问题