_ctypes.cpython-39-x86_64-linux-gnu.so: undefined symbol: PyFloat_Type in embedded Python loaded with dlopen(_ctyes.cpython-39-x86_64-linux-gnU.S.so:未定义的符号:使用dlopen加载的Embedded Python中的PyFloat_Type)
问题描述
我使用的是ubuntu 20.04中的Embedded Python(3.9),尝试导入ctype时出现错误_ctypes.cpython-39-x86_64-linux-gnu.so: undefined symbol: PyFloat_Type。
我正在编译共享对象,它是使用dlopen()动态加载的。
CMake用于构建共享对象。我这样说明对Python3的依赖关系:
find_package(Python3 REQUIRED COMPONENTS Development Development.Embed)和使用target_link_libraries(${target_name} Boost::filesystem Python3::Python)链接
如果我理解正确的话,这会告诉CMake直接与libpython3.9.so链接(我还试图显式声明链接到libpython3.9.so,但这并没有解决问题)。
我确实看到libpython3.9.so导出PyFloat_Type,而_ctypes.cpython-39-x86_64-linux-gnu.so不导出。
导入只需PyRun_SimpleString()函数:PyRun_SimpleString("import ctypes")即可完成。
我应该声明,我在Web上看到了一些解决方案,但没有一个奏效(如导出LD_FLAGS="-rdynamic",但也没有帮助)。
我还应该指出,使用解释器(python3.9)导入效果很好。
以下是CMake生成的构建命令:
/usr/bin/c++ -fPIC -g -Xlinker -export-dynamic -shared -Wl,-soname,mytest.python3.so -o mytest.python3.so CMakeFiles/mytest.python3.dir/[mydir]/[myobjects].o  /usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.71.0 /usr/lib/x86_64-linux-gnu/libpython3.9.so /usr/lib/x86_64-linux-gnu/libpython3.9.so
提前感谢您的帮助!
推荐答案
当在Linux上的CPython中导入C扩展时,dlopen在幕后使用(默认情况下使用RTLD_LOCAL-FLAG)。
libpythonX.Y.so)的功能,例如PyFloat_Type。然而,在Linux上,C扩展没有链接到libpythonX.Y.so(Windows上的情况不同,有关更多详细信息,请参阅this或this)--缺少的函数定义/功能将由python可执行文件提供。
若要执行此操作,可执行文件必须与-Xlinker -export-dynamic链接,否则加载程序将无法将可执行文件中的符号用于通过dlopen加载的共享对象。
dlopen本身一起加载的共享对象,我们需要确保将其符号添加到动态表中。使用-Xlinker -export-dynamic构建这个共享对象没有多大意义(它毕竟不是可执行文件),但不会破坏任何东西--重要的部分是如何使用dlopen。
为了使text.python.so中的符号对以后使用dlopen加载的共享对象可见,应使用RTLD_GLOBAL标志打开它:
RTLD_GLOBAL 将制作由该共享对象定义的符号 可用于后续加载的符号解析 共享对象。
即
shared_lib = dlopen(path_to_so_file, RTLD_GLOBAL | RTLD_NOW);
警告:RTLD_LAZY不应使用。
RTLD_LAZY的问题是,C扩展不依赖于libpython(可以通过ldd看到),因此一旦它们被加载并且来自libpython的尚未解析的符号(例如PyFloat_Type)必须被查找,动态链接器不知道它必须查找libpython。
另一方面,使用RTLD_NOW时,所有符号都被解析并在加载C扩展时可见(这与在与-Xlinker -export-dynamic的链接步骤中链接libpython时的情况相同),因此不会出现查找问题,例如PyFloat_Type-符号。
只要用dlopen加载嵌入的python,就不需要用-Xlinker -export-dynamic构建/链接主可执行文件。
但是,如果主可执行文件是针对Embedded-python-Shared-Object链接的,则-Xlinker -export-dynamic是必需的,否则在导入c-扩展时使用dlopen时,希望可以看到python符号。
有人可能会问,为什么不首先将C扩展与libpython联系起来?
由于使用了RTLD_LOCAL,每个C扩展都会有自己的(未初始化的)版本的Python解释器(因为不会插入来自libpython的符号),并且一旦使用就会崩溃。
若要使其正常工作,dlopen应使用RTLD_GLOBAL标志打开-但这不是合理的默认选项。
这篇关于_ctyes.cpython-39-x86_64-linux-gnU.S.so:未定义的符号:使用dlopen加载的Embedded Python中的PyFloat_Type的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:_ctyes.cpython-39-x86_64-linux-gnU.S.so:未定义的符号:使用dlopen加载的Embedded Python中的PyFloat_Type
 
				
         
 
            
        基础教程推荐
- 无法导入 Pytorch [WinError 126] 找不到指定的模块 2022-01-01
- 包装空间模型 2022-01-01
- PANDA VALUE_COUNTS包含GROUP BY之前的所有值 2022-01-01
- 在同一图形上绘制Bokeh的烛台和音量条 2022-01-01
- Plotly:如何设置绘图图形的样式,使其不显示缺失日期的间隙? 2022-01-01
- 求两个直方图的卷积 2022-01-01
- 修改列表中的数据帧不起作用 2022-01-01
- 在Python中从Azure BLOB存储中读取文件 2022-01-01
- PermissionError: pip 从 8.1.1 升级到 8.1.2 2022-01-01
- 使用大型矩阵时禁止 Pycharm 输出中的自动换行符 2022-01-01
 
    	 
    	 
    	 
    	 
    	 
    	 
    	 
    	 
				 
				 
				 
				