如何通过C语言调用Cython编译生成的.pyd模块中的函数?
纯C代码调用Cython生成的.pyd模块函数解决方案
核心前提
.pyd本质是Python扩展模块,不是普通独立DLL,必须依托Python解释器才能运行,不能直接用LoadLibrary+GetProcAddress调用其中的函数。
步骤1:确保Cython函数正确导出
在你的Cython源码(如CythonModule.pyx)中,用cdef public声明要暴露的函数:
cdef public void PyFuncSwo(): # 函数实现逻辑 print("Executing PyFuncSwo from Cython")
重新编译项目:
python setup.py build_ext --inplace
确认生成对应的CythonModule.h头文件,其中会包含函数声明:
extern void PyFuncSwo(void);
步骤2:编写纯C调用代码
必须先初始化Python解释器,再加载模块并通过Python接口获取函数指针。示例代码如下:
#include <Python.h> #include "CythonModule.h" int main() { // 初始化Python解释器 Py_Initialize(); // 将.pyd所在目录添加到Python搜索路径(若不在默认路径) PyObject* sys_path = PySys_GetObject("path"); PyList_Append(sys_path, PyUnicode_FromString(".")); // 假设.pyd在当前运行目录 // 导入Cython模块 PyObject* module = PyImport_ImportModule("CythonModule"); if (!module) { PyErr_Print(); return 1; } // 通过Python Capsule机制获取函数指针 void (*func_ptr)(void) = (void (*)())PyCapsule_GetPointer( PyObject_GetAttrString(module, "PyFuncSwo"), NULL ); if (!func_ptr) { PyErr_Print(); Py_DECREF(module); Py_Finalize(); return 1; } // 调用目标函数 func_ptr(); // 清理资源 Py_DECREF(module); Py_Finalize(); return 0; }
步骤3:解决编译链接错误
编译时需要链接Python导入库,并指定.pyd文件路径:
- Windows(MSVC编译器)命令示例:
cl /I"C:\Python39\include" your_c_code.c /link /LIBPATH:"C:\Python39\libs" python39.lib CythonModule.cp39-win_amd64.pyd
- 关键说明:
/I指定Python头文件目录/LIBPATH指定Python库文件目录- 必须链接对应版本的Python导入库(如
python39.lib) - 将生成的.pyd文件作为链接依赖项
常见问题解释
为什么
LoadLibrary找不到函数?
.pyd模块不会将cdef public函数直接导出为DLL符号,而是通过Python的Capsule机制在模块加载后暴露,必须通过Python解释器接口获取。为什么出现
undefined reference to 'PyInit_CythonModule'?
编译时未正确链接Python库或.pyd模块,确保编译命令中包含Python导入库和.pyd文件的链接参数。
内容的提问来源于stack exchange,提问作者sdfdf
相关产品推荐
相关产品推荐

