You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu20.04下dlopen加载嵌入式Python3.9导入ctypes报PyFloat_Type错误

问题根因

该错误的核心是dlopen加载你的共享对象时,默认不会将共享对象依赖的libpython3.9.so的符号导出到全局符号表。ctypes依赖的扩展模块_ctypes.cpython-39-x86_64-linux-gnu.so加载时会从全局符号表查找PyFloat_Type这类Python核心符号,找不到就会抛出未定义符号错误。你直接运行官方python3.9解释器时,解释器进程启动时会提前将libpython的符号加载到全局符号表,因此导入ctypes正常。
你之前尝试的-rdynamic参数仅用于导出当前编译目标自身的符号,无法将其依赖的第三方库符号导出到全局,因此无法解决该问题。

可行解决方案

按改造成本从低到高排序:

  • 调整dlopen加载参数:加载你的mytest.python3.so时,在flag中添加RTLD_GLOBAL,将当前库及依赖库的所有符号导出到全局符号表,示例代码:
    void* handle = dlopen("mytest.python3.so", RTLD_NOW | RTLD_GLOBAL);
    
    该方案不需要修改现有CMake配置,改造成本最低。
  • 调整CMake链接配置:如果你无法修改dlopen的调用逻辑,可以在CMakeLists.txt中给你的目标添加链接标记,强制加载所有libpython符号:
    set_target_properties(${target_name} PROPERTIES LINK_FLAGS "-Wl,--no-as-needed")
    
    该参数会强制链接器不做按需符号裁剪,将libpython3.9.so的所有符号都纳入导出范围。
  • 手动预加载libpython:如果前两种方案都不适用,可以在初始化Python解释器、加载你的共享对象之前,手动预加载libpython3.9.so并开启全局符号导出:
    // 提前加载libpython到全局符号表
    dlopen("/usr/lib/x86_64-linux-gnu/libpython3.9.so", RTLD_NOW | RTLD_GLOBAL);
    // 后续再执行dlopen加载你的共享对象、初始化Python的逻辑
    
验证方法

修改完成后可通过以下方式确认修复效果:

  1. 执行nm -D mytest.python3.so | grep PyFloat_Type确认符号已导出
  2. 运行程序时添加环境变量LD_DEBUG=symbols,查看PyFloat_Type的查找路径是否匹配libpython3.9.so

内容的提问来源于stack exchange,提问作者TCS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.17 09:06:04