PyBind11封装外部.so库后Python导入报未定义符号问题求助
问题:PyBind11封装外部库后导入出现未定义符号错误
错误现象
导入封装模块时触发以下错误:
/home/user/dev/external/Python/PyBind_Module/external_python.cpython-310-x86_64-linux-gnu.so: undefined symbol: <FUNCTION> File "/home/user/dev/external/Python/pybind_test.py", line 3, in <module> import external_wrapper as exw ImportError: /home/user/dev/external/Python/PyBind_Module/external_python.cpython-310-x86_64-linux-gnu.so: undefined symbol: <FUNCTION>
执行nm -gD命令确认目标函数已在外部库的导出符号列表中:
nm -gD /usr/lib/libexternal.so | grep 'FUNCTION' 00000000000170c0 T FUNCTION 0000000000018ff0 T FUNCTIONd
当前使用的setup.py代码
from pathlib import Path from pybind11.setup_helpers import build_ext from pybind11.setup_helpers import Pybind11Extension from setuptools import setup example_module = Pybind11Extension( "external_python", sources=[str(fname) for fname in Path("src").glob("*.cpp")], include_dirs=["include", "."], extra_compile_args=["-O3"], libraries=["/usr/lib/libexternal.so"], library_dirs=["/usr/lib"] ) setup( name="external_module", version=1.0, description="C++ wrapper around the external library", ext_modules=[example_module], cmdclass={"build_ext": build_ext}, )
解决方案
1. 修正setup.py的链接参数写法
libraries参数只需传入库的名称(去掉前缀lib和后缀.so),不需要完整路径。修改后:
example_module = Pybind11Extension( "external_python", sources=[str(fname) for fname in Path("src").glob("*.cpp")], include_dirs=["include", "."], extra_compile_args=["-O3"], libraries=["external"] # 仅保留库名 )
注:/usr/lib是系统默认的库搜索路径,因此可以省略library_dirs参数。
2. 添加运行时库搜索路径(可选)
如果编译后的模块仍无法在运行时找到依赖库,可通过extra_link_args添加-rpath参数,硬编码库的搜索路径:
example_module = Pybind11Extension( "external_python", sources=[str(fname) for fname in Path("src").glob("*.cpp")], include_dirs=["include", "."], extra_compile_args=["-O3"], libraries=["external"], extra_link_args=["-Wl,-rpath=/usr/lib"] # 指定运行时库路径 )
3. 验证链接状态
编译完成后,用ldd命令检查生成的模块是否正确链接到目标库:
ldd /home/user/dev/external/Python/PyBind_Module/external_python.cpython-310-x86_64-linux-gnu.so
若输出中显示libexternal.so => /usr/lib/libexternal.so,说明链接正常。
4. 检查C++名字修饰问题
如果外部库是C编写的,需确保封装代码中用extern "C"声明函数,避免C名字修饰导致符号不匹配:
#ifdef __cplusplus extern "C" { #endif // 外部库函数声明 void FUNCTION(); #ifdef __cplusplus } #endif
内容的提问来源于stack exchange,提问作者SinisterMJ
相关产品推荐
相关产品推荐

