如何获取正确cflags与ldflags 实现Python嵌入C跨平台可执行文件
问题根本原因
你当前的编译命令只指定了头文件搜索路径,没有添加链接Python运行时库的参数,所有未定义符号都是Python核心库的导出函数,属于典型的缺失链接目标的问题,同时python*-config默认返回参数不全、编译参数顺序错误也会导致编译失败。
可靠参数获取方案
所有平台都优先用当前要嵌入的Python解释器本身的sysconfig模块获取完整参数,不要直接用默认的python*-config,大多数发行版、第三方包管理器安装的Python对应的python*-config返回的参数默认是不全的,需要手动指定输出项。
1. GCC/Clang 场景(Linux/macOS通用)
直接在终端执行你要嵌入的Python解释器命令,输出完整的编译和链接参数:
- 获取完整CFLAGS(含全部头文件路径):
python3 -c "import sysconfig; print(' '.join(sysconfig.get_config_vars('CFLAGS', 'INCLUDES')))" - 获取完整LDFLAGS(含库路径、依赖库名):
python3 -c "import sysconfig; print(' '.join(sysconfig.get_config_vars('LDFLAGS', 'LIBS', 'SYSLIBS', 'MODLIBS')) + ' -lpython' + sysconfig.get_config_var('VERSION'))"
拿到参数后直接代入编译命令即可,注意链接参数必须放在源文件/目标文件后面,GCC/Clang对链接顺序有严格要求,示例如下:
gcc $(python3 -c "import sysconfig; print(' '.join(sysconfig.get_config_vars('CFLAGS', 'INCLUDES')))") test.c -o test $(python3 -c "import sysconfig; print(' '.join(sysconfig.get_config_vars('LDFLAGS', 'LIBS', 'SYSLIBS', 'MODLIBS')) + ' -lpython' + sysconfig.get_config_var('VERSION'))")
macOS下如果是Homebrew安装的Python,运行上述命令会自动适配框架路径,无需额外手动配置。
2. MSVC 场景(Windows)
Windows下同样用对应Python解释器输出适配MSVC语法的参数:
- 获取头文件路径参数:
py -3 -c "import sysconfig; print('/I\"' + sysconfig.get_path('include') + '\"')" - 获取库文件搜索路径参数:
py -3 -c "import sysconfig; print('/LIBPATH:\"' + sysconfig.get_path('stdlib') + '\..\libs\"')" - 获取要链接的Python库名:
py -3 -c "import sysconfig; print('python' + sysconfig.get_config_var('VERSION').replace('.', '') + '.lib')"
把三个参数分别加到MSVC的编译选项、链接选项里即可,示例完整编译命令:
cl test.c /I"C:\Python39\include" /link /LIBPATH:"C:\Python39\libs" python39.lib /OUT:test.exe
注意事项
- 必须保证你用的编译器架构(x86/x64/ARM)和你要嵌入的Python解释器架构完全一致,否则会出现架构不匹配的链接错误
- 不要混用不同版本Python的参数,要用哪个版本嵌入就用哪个版本的解释器执行上述命令获取参数
- 优先用虚拟环境里的Python解释器获取参数,避免全局多版本Python冲突
内容的提问来源于stack exchange,提问作者Josh Weinstein
相关产品推荐
相关产品推荐

