编译使用Python.h的C++项目时的问题 -> 未定义引用
我在Windows上用g++编译我的C++项目时遇到了问题。
这是我的代码:
#include <python.h>
int main(int argc, char **argv)
{
Py_Initialize();
PyRun_SimpleString("print('Hello World!')");
Py_Finalize();
return 0;
}
我使用的命令是:
g++ -I C:\Python310\include main.cpp -o output -L C:\Python310\libs -lpython310
但是它总是给我这个关于未定义引用的错误:
AppData\Local\Temp\ccQdtubj.o:main.cpp:(.text+0x1f): undefined reference to `_imp__Py_DecodeLocale'
AppData\Local\Temp\ccQdtubj.o:main.cpp:(.text+0x6c): undefined reference to `_imp__Py_SetProgramName'
AppData\Local\Temp\ccQdtubj.o:main.cpp:(.text+0x73): undefined reference to `_imp__Py_Initialize'
AppData\Local\Temp\ccQdtubj.o:main.cpp:(.text+0x8d): undefined reference to `_imp__PyRun_SimpleStringFlags'
AppData\Local\Temp\ccQdtubj.o:main.cpp:(.text+0x94): undefined reference to `_imp__Py_FinalizeEx'
AppData\Local\Temp\ccQdtubj.o:main.cpp:(.text+0xb5): undefined reference to `_imp__PyMem_RawFree'
collect2.exe: error: ld returned 1 exit status
1 个回答
Could not find platform dependent libraries <exec_prefix>
你正在尝试将一个用Windows的 g++
编译的程序 (x86_64-w64-mingw32-g++.exe
) 和一个用微软的MSVC构建的导入库 C:/Python310/libs/python310.lib
连接起来。这样做是行不通的,因为 x86_64-w64-mingw32
的库和MSVC的库不兼容。你需要获取 x86_64-w64-mingw32
的Python库,适用于MSYS2,并使用它的头文件和库进行构建。
建议你安装并使用 MSYS2 作为你在Windows上的 gcc/g++
开发环境。
在这个环境下,编译和链接的命令行(使用Windows文件系统)应该像这样:
# Link with explicitly versioned import library
g++ -I C:\msys64\mingw64\include -I C:\msys64\mingw64\include\python3.11 main.cpp \
-o output -L C:\msys64\mingw64\lib -lpython3.11
或者:
# Link with unversioned import library
g++ -I C:\msys64\mingw64\include -I C:\msys64\mingw64\include\python3.11 main.cpp \
-o output -L C:\msys64\mingw64\lib -lpython3
在msys64环境中,导入库的命名方式和Windows不同,不叫 name.lib
,而是叫 libname.dll.a
,例如 C:\msys64\mingw64\lib\libpython3.dll.a
是 C:\msys64\mingw64\bin\libpython3.dll
的导入库。
后续
@MatyVymlátil 评论说:
我用了你给我的第二个命令,没报关于Python库的错误,但报了关于 'PyRun_SimpleStringFlags' 的未定义引用,我不知道为什么。
结果发现 PyRun_SimpleStringFlags
在 libpython3.dll.a
中是未定义的,但在 libpython3.11.dll.a
中是定义的。假设(看起来是对的)你已经把 PATH
扩展为 C:\msys64\mingw64\bin;C:\msys64\mingw64\x86_64-w64-min\bin
,你可以在Powershell中这样检查:
> nm C:\msys64\mingw64\lib\libpython3.dll.a | findstr PyRun_SimpleStringFlags; echo Done
Done
与之对比:
> nm C:\msys64\mingw64\lib\libpython3.11.dll.a | findstr PyRun_SimpleStringFlags; echo Done
0000000000000000 I __imp_PyRun_SimpleStringFlags
0000000000000000 T PyRun_SimpleStringFlags
Done
或者在MSYS2的命令行(相当于Linux的bash)中这样:
$ nm /c/msys64/mingw64/lib/libpython3.dll.a | grep PyRun_SimpleStringFlags; echo Done
Done
$ nm /c/msys64/mingw64/lib/libpython3.11.dll.a | grep PyRun_SimpleStringFlags; echo Done
0000000000000000 I __imp_PyRun_SimpleStringFlags
0000000000000000 T PyRun_SimpleStringFlags
Done
查看 nm手册
这意味着你必须使用第一个命令才能成功链接。在Powershell中:
> g++ -I C:\msys64\mingw64\include -I C:\msys64\mingw64\include\python3.11 main.cpp -o output -L C:\msys64\mingw64\lib -l python3.11
> .\output.exe
Could not find platform dependent libraries <exec_prefix>
Hello World!
或者在MSYS2命令行中:
$ g++ -I /c/msys64/mingw64/include -I /c/msys64/mingw64/include/python3.11 main.cpp -o output -L /c/msys64/mingw64/lib -l python3.11
$ ./output.exe
Could not find platform dependent libraries <exec_prefix>
Hello World!
如果你没有在启动 output.exe
的环境中正确设置环境变量 PYTHONHOME
和 PYTHONPATH
,就会出现这个警告。
你可以设置这些变量,让警告消失。在Powershell中:
> $env:pythonhome = "C:\msys64\\mingw64\lib\"
> $env:pythonpath = "C:\msys64\mingw64\lib\python3.11"
> .\output.exe
Hello World!
或者在MSYS2命令行中:
$ export PYTHONHOME=/c/msys64/mingw64/lib
$ export PYTHONPATH=/c/msys64/mingw64/lib/python3.11
$ ./output.exe
Hello World!
当然,你也可以在Windows的用户配置或系统配置中永久设置这些变量。
你还可以在程序内部设置这些环境变量,然后再调用 Py_Initialize
,但这样做会显得过于死板。