Cython生成C代码编译遇R_X86_64_32重定位错误,求解决方案
解决Cython编译HelloWorld时的链接错误问题
我来帮你搞定这个编译报错的问题,咱们先理清楚根源,再给出正确的解决方案:
问题到底出在哪?
第一个报错是PIE(位置独立可执行文件)相关的重定位冲突:Ubuntu 18.04默认会编译生成PIE可执行文件,但python3-config返回的参数里带了-specs=/usr/share/dpkg/no-pie-compile.specs,这会让编译阶段生成非PIE的目标文件,链接阶段默认要做PIE链接,就出现了不匹配的重定位错误。
你后来加-fPIC的操作方向是对的,但参数顺序搞错了——GCC对参数顺序很敏感:编译选项要放在源文件前面,链接选项(比如链接Python库的参数)要放在源文件后面。你之前把-fPIC放在--ldflags之后,不仅没起到编译阶段的作用,还打乱了链接库的顺序,导致Python的函数找不到定义。
正确的编译命令
有两种可行的修复方式,选一种就行:
方式一:用-fPIC编译 + 正确的参数顺序
把编译选项放在源文件前,链接选项放在源文件后:
gcc -fPIC `/usr/bin/python3-config --cflags` helloworld.c -o helloworld `/usr/bin/python3-config --ldflags`
方式二:显式指定生成非PIE可执行文件
既然python3-config已经带了关闭PIE编译的参数,那链接阶段也明确关闭PIE:
gcc `/usr/bin/python3-config --cflags` helloworld.c -o helloworld `/usr/bin/python3-config --ldflags` -no-pie
为什么这两种方式能解决问题?
- 参数顺序的重要性:GCC从左到右处理参数,先处理编译选项(比如
-fPIC、--cflags里的头文件路径、编译警告等),再处理源文件,最后处理链接选项(--ldflags里的库路径、链接的库,还有-no-pie这种链接控制参数)。这样GCC能正确找到Python的头文件,编译出符合要求的目标文件,再正确链接Python的库,就不会出现未定义引用了。 - PIE冲突的解决:方式一是让编译生成位置独立的目标文件,适配默认的PIE链接;方式二是让链接阶段也生成非PIE可执行文件,和编译阶段的输出匹配,两种都能解决重定位错误。
验证一下
- 确认已经生成了
helloworld.c:cython --embed helloworld.py - 用上面的任意一个命令编译;
- 运行生成的可执行文件:
正常情况下会输出./helloworldHello World。
内容的提问来源于stack exchange,提问作者Kuba Chrabański
相关产品推荐
相关产品推荐

