Cython导入共享对象报错:undefined symbol问题排查求助
问题排查与解决
你遇到的undefined symbol错误,核心原因是C++的名字修饰(Name Mangling)加上函数参数签名不匹配导致的,下面一步步拆解解决:
1. 解决C++函数的名字修饰问题
C编译器会对函数名进行特殊的“名字修饰”来支持重载特性,但Cython是按照C语言的规则查找未修饰的函数名,所以链接时找不到对应符号。我们需要让C函数以C语言的链接规则编译:
修改头文件AGc.h
用extern "C"包裹函数声明,告诉编译器按C的规则生成符号,同时把引用参数改为指针(C语言不支持引用):
#ifdef __cplusplus extern "C" { #endif void c_Stat_GetMeanAndVariance_double(const double *aData, const int nSize, double *mean, double *var); #ifdef __cplusplus } #endif
修改C++实现文件AGc.cpp
调整函数参数为指针,并修改内部赋值逻辑(用*mean和*var代替原有的引用变量):
#include "AGc.h" void c_Stat_GetMeanAndVariance_double(const double *aData, const int nSize, double *mean, double *var) { // Special case, small vector if (nSize<=1) { *var = 0; if (nSize) *mean = *aData; else *mean = 0; return; } double s, ssqr; Stat_GetSums_double(aData, nSize, s, ssqr); *mean = s/nSize; *var = Stat_GetVariance(s, ssqr, nSize); return; }
2. 确认Cython声明的正确性
你当前AGCython.pyx里的函数声明完全匹配修改后的C++函数参数,无需调整:
cdef extern void c_Stat_GetMeanAndVariance_double (double* array, int nSize, double* mean, double* var)
调用时传递&mean、&var的写法也完全符合指针参数的要求。
3. 修复编译脚本的语言指定
你的编译脚本没有明确指定用C编译器处理代码,虽然最终链接用了g,但编译.cpp文件时用了gcc,可能引发潜在问题。修改setup.py,给Extension添加language="c++"参数:
from distutils.core import setup from Cython.Build import cythonize from distutils.extension import Extension import numpy sourcefiles = ['AGCython.pyx', 'AGc.cpp'] # 添加language参数,强制使用C++编译器编译所有源文件 extensions = [Extension("AGCython", sourcefiles, language="c++")] setup( ext_modules = cythonize(extensions, annotate=True) )
4. 重新编译验证
先清理之前的编译产物(build目录、生成的.so文件),再重新执行编译:
python setup.py build_ext --inplace
编译完成后尝试导入AGCython,应该就能正常运行了。
如果仍有问题,可以用nm命令检查.so文件是否包含目标符号:
nm -D AGCython.cpython-36m-x86_64-linux-gnu.so | grep c_Stat_GetMeanAndVariance_double
若输出包含T c_Stat_GetMeanAndVariance_double,说明符号已正确导出;若没有输出,需检查编译过程是否正确包含了AGc.cpp的代码。
内容的提问来源于stack exchange,提问作者L.E.
相关产品推荐
相关产品推荐

