编译使用Python.h的C++项目时的问题 -> 未定义引用

0 投票
1 回答
50 浏览
提问于 2025-04-12 03:44

我在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 个回答

0
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.aC:\msys64\mingw64\bin\libpython3.dll 的导入库。

后续

@MatyVymlátil 评论说:

我用了你给我的第二个命令,没报关于Python库的错误,但报了关于 'PyRun_SimpleStringFlags' 的未定义引用,我不知道为什么。

结果发现 PyRun_SimpleStringFlagslibpython3.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 的环境中正确设置环境变量 PYTHONHOMEPYTHONPATH,就会出现这个警告。

你可以设置这些变量,让警告消失。在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,但这样做会显得过于死板。

撰写回答