将带头文件的C++类编译为so库供Python调用,符号未定义报错如何解决
错误原因
extern "C"使用错误:extern "C"仅能对C风格的函数声明生效,你将包含C命名空间、类定义的头文件包裹在extern "C"块中不会改变类成员函数的编译逻辑,my_class::hello_world还是会被C编译器做名字修饰(Name Mangling),最终导出的符号名是类似_ZN1N8my_class11hello_worldEv的修饰后名称,ctypes按hello_world原名自然找不到对应符号。- ctypes不支持直接调用C++类成员函数:C++类的非静态成员函数隐含
this指针参数,调用约定和普通C函数完全不同,就算你找到修饰后的符号名,直接调用也会出现内存错误。
修复方案
步骤1:修改C++实现代码,新增C风格导出接口
不需要修改my_class.h,仅调整my_class.cpp,新增对外暴露的C风格包装函数,显式用extern "C"修饰避免名字修饰,同时封装类的创建、方法调用、销毁逻辑:
// my_class.cpp #include "my_class.h" #include <iostream> using namespace N; using namespace std; void my_class::hello_world() { cout << "Hello, World!" << endl; } // 对外暴露的C风格接口 extern "C" { // 创建my_class实例,返回指针 void* create_my_class() { return new my_class(); } // 调用hello_world方法,传入实例指针 void my_class_hello_world(void* instance) { static_cast<my_class*>(instance)->hello_world(); } // 销毁my_class实例,避免内存泄漏 void destroy_my_class(void* instance) { delete static_cast<my_class*>(instance); } }
步骤2:重新编译生成共享库
编译命令无需调整,直接执行即可:
g++ -fPIC -shared -o my_class.so my_class.cpp
步骤3:修改Python调用代码
通过暴露的C接口完成类操作:
import ctypes # 加载共享库 lib = ctypes.cdll.LoadLibrary('./my_class.so') # 创建类实例 instance = lib.create_my_class() # 调用hello_world方法 lib.my_class_hello_world(instance) # 销毁实例,释放内存 lib.destroy_my_class(instance)
内容的提问来源于stack exchange,提问作者ajawa
相关产品推荐
相关产品推荐

