Cython嵌入Python至C程序:链接embed.o失败求助
链接嵌入Python的C程序时出现未定义引用错误
问题详情
我是刚接触将Python源码嵌入C程序的新手,编写了基础程序创建名为introduction的Cython模块,模块包含同名函数:
cdef char* introduction(char* name, char* lastName): return "Hello, {} {}!".format(name, lastName).encode("utf-8")
随后编写了如下C程序调用该模块:
/** File : embed.c Project : None Programmer : Braiden Gole First version : 2023-04-22 Description : This is my first embeded python program. NOTE: Where Python is located. NOTE: C:\Users\<my_username>\AppData\Local\Programs\Python\Python311\include NOTE: "C:\Users\<my_username>\AppData\Local\Programs\Python\Python311\libs\python311.lib" NOTE: "C:\Users\<my_username>\AppData\Local\Programs\Python\Python311\python311.dll" COMPILE: gcc -c embed.c -o embed.o -IC:/Users/<my_username>/AppData/Local/Programs/Python/Python311/include LINK: gcc -o embed embed.o -IC:/Users/<my_username>/AppData/Local/Programs/Python/Python311/include -LC:/Users/<my_username>/AppData/Local/Programs/Python/Python311/libs -lpython311 */ #include <stdio.h> #include <Python.h> int main(int argc, char* argv[]) { // Initialize the python interpreter. Py_Initialize(); // Import the CPython module. PyObject* pModule = PyImport_ImportModule("introduction"); if (!pModule) { printf("%s", "Failed to imprt python module."); return 1; } PyObject* pFunction = PyObject_GetAttrString(pModule, "introduction"); if (!pFunction || !PyCallable_Check(pFunction)) { printf("%s", "Failed to get python function."); return 1; } // Create a tuple and set the arguments of the function. PyObject* pArguments = PyTuple_New(2); PyTuple_SetItem(pArguments, 0, PyUnicode_FromString("Braiden")); PyTuple_SetItem(pArguments, 1, PyUnicode_FromString("Gole")); PyObject* pResult = PyObject_CallObject(pFunction, pArguments); Py_DECREF(pArguments); if (!pResult) { printf("%s", "Failed to call python function."); return 1; } char* introduction = PyBytes_AsString(pResult); printf("%s", introduction); Py_DECREF(pResult); // Clean up resources. Py_DECREF(pFunction); Py_DECREF(pModule); Py_Finalize(); return 0; }
注释中的路径为系统实际路径,已确认目录和文件均存在。可以成功编译embed.c,但无法链接目标文件embed.o。
环境说明
- Python已添加至PATH
- 已安装Python调试符号
- 已安装Python调试二进制文件
- 当前使用Python 3.11.3,曾尝试链接Python 3.10,问题依旧
链接错误信息
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0x23): undefined reference to `_imp___Py_Dealloc' c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0x3b): undefined reference to `_imp__Py_Initialize' c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0x49): undefined reference to `_imp__PyImport_ImportModule' c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0x88): undefined reference to `_imp__PyObject_GetAttrString' c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0xa1): undefined reference to `_imp__PyCallable_Check' c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0xd1): undefined reference to `_imp__PyTuple_New' c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0xe3): undefined reference to `_imp__PyUnicode_FromString' c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0xfd): undefined reference to `_imp__PyTuple_SetItem' c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0x10b): undefined reference to `_imp__PyUnicode_FromString' c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0x125): undefined reference to `_imp__PyTuple_SetItem' c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0x13b): undefined reference to `_imp__PyObject_CallObject' c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0x17b): undefined reference to `_imp__PyBytes_AsString' c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0x1be): undefined reference to `_imp__Py_Finalize' collect2.exe: error: ld returned 1 exit status
解决方法
1. 生成MinGW兼容的Python静态库
Windows官方Python是用MSVC编译的,MinGW无法直接链接其提供的.lib文件,需要生成MinGW可用的.a库:
- 下载
gendef工具(通常随MinGW或单独提供) - 进入Python的dll所在目录(
C:\Users\<my_username>\AppData\Local\Programs\Python\Python311) - 执行以下命令生成
.def文件和.a库:
gendef python311.dll dlltool -D python311.dll -d python311.def -l libpython311.a
- 将生成的
libpython311.a复制到Python的libs目录下
2. 调整链接命令
链接时确保-lpython311放在目标文件之后,并且指定正确的库路径:
gcc -o embed embed.o -IC:/Users/<my_username>/AppData/Local/Programs/Python/Python311/include -LC:/Users/<my_username>/AppData/Local/Programs/Python/Python311/libs -lpython311
如果.a库在当前目录,添加-L.参数。
3. 匹配编译位数与宏定义
- 确保MinGW的位数和Python一致(32位MinGW对应32位Python,64位对应64位)
- 编译时添加对应宏定义:
32位Python:
64位Python:gcc -c embed.c -o embed.o -IC:/Users/<my_username>/AppData/Local/Programs/Python/Python311/include -DMS_WIN32gcc -c embed.c -o embed.o -IC:/Users/<my_username>/AppData/Local/Programs/Python/Python311/include -DMS_WIN64
4. 其他注意事项
- 确保Python的
python311.dll所在目录已加入系统PATH,或者将dll复制到生成的可执行文件同目录下 - 运行程序前,确保
introduction模块所在目录在Python的搜索路径中(可通过设置PYTHONPATH环境变量)
内容的提问来源于stack exchange,提问作者user15746554
相关产品推荐
相关产品推荐

