gcc 编译官方文档“在另一个应用程序中嵌入Python”示例失败

j7dteeu8  于 2022-11-13  发布在  Python
关注(0)|答案(2)|浏览(121)

我尝试编译并运行www.example.com中的示例https://docs.python.org/3/extending/embedding.html#very-high-level-embedding,但失败了。
我的环境是Ubuntu 20.04.2 LTS,系统附带了python3.8(静态构建),安装了libpython3-devlibpython3.8-dev包。
我尝试过的方法:
主. c:

#define PY_SSIZE_T_CLEAN
#include <Python.h>

int
main(int argc, char *argv[])
{
    wchar_t *program = Py_DecodeLocale(argv[0], NULL);
    if (program == NULL) {
        fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
        exit(1);
    }
    Py_SetProgramName(program);  /* optional but recommended */
    Py_Initialize();
    PyRun_SimpleString("from time import time,ctime\n"
                       "print('Today is', ctime(time()))\n");
    if (Py_FinalizeEx() < 0) {
        exit(120);
    }
    PyMem_RawFree(program);
    return 0;
}

从类似Unix系统下的编译与链接,取得gcc旗标。

tian@tian-B250M-Wind:~$ python3-config --cflags
-I/usr/include/python3.8 -I/usr/include/python3.8  -Wno-unused-result -Wsign-compare -g -fdebug-prefix-map=/build/python3.8-4wuY7n/python3.8-3.8.10=. -specs=/usr/share/dpkg/no-pie-compile.specs -fstack-protector -Wformat -Werror=format-security  -DNDEBUG -g -fwrapv -O3 -Wall
tian@tian-B250M-Wind:~$ python3-config --ldflags
-L/usr/lib/python3.8/config-3.8-x86_64-linux-gnu -L/usr/lib  -lcrypt -lpthread -ldl  -lutil -lm -lm

(我不知道为什么python3-config输出有一些重复的值,这不是键入错误)
gcc {copy cflags output} -o main main.c /path_to_libpython/libpython3.8.a {copy ld flags output}

gcc -I/usr/include/python3.8 -I/usr/include/python3.8  -Wno-unused-result -Wsign-compare -g -fdebug-prefix-map=/build/python3.8-4wuY7n/python3.8-3.8.10=. -specs=/usr/share/dpkg/no-pie-compile.specs -fstack-protector -Wformat -Werror=format-security  -DNDEBUG -g -fwrapv -O3 -Wall -o main main.c /usr/lib/python3.8/config-3.8-x86_64-linux-gnu/libpython3.8.a -L/usr/lib/python3.8/config-3.8-x86_64-linux-gnu -L/usr/lib  -lcrypt -lpthread -ldl  -lutil -lm -lm

make test1产生错误,几乎所有错误都与-fPIE相关:

/usr/bin/ld: /tmp/ccdMZ2Yk.o: relocation R_X86_64_32 against `.rodata.str1.8' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/lib/python3.8/config-3.8-x86_64-linux-gnu/libpython3.8.a(obmalloc.o): relocation R_X86_64_32 against `.text.hot' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/lib/python3.8/config-3.8-x86_64-linux-gnu/libpython3.8.a(initconfig.o): relocation R_X86_64_32 against symbol `_PyRuntime' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/lib/python3.8/config-3.8-x86_64-linux-gnu/libpython3.8.a(pathconfig.o): relocation R_X86_64_32 against symbol `_Py_path_config' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/lib/python3.8/config-3.8-x86_64-linux-gnu/libpython3.8.a(preconfig.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/lib/python3.8/config-3.8-x86_64-linux-gnu/libpython3.8.a(pylifecycle.o): relocation R_X86_64_32 against symbol `_PyRuntime' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/lib/python3.8/config-3.8-x86_64-linux-gnu/libpython3.8.a(pystate.o): relocation R_X86_64_32 against `.rodata.str1.8' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/lib/python3.8/config-3.8-x86_64-linux-gnu/libpython3.8.a(pythonrun.o): relocation R_X86_64_32 against symbol `_PyParser_Grammar' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/lib/python3.8/config-3.8-x86_64-linux-gnu/libpython3.8.a(pytime.o): relocation R_X86_64_32S against symbol `PyFloat_Type' can not be used when making a PIE object; recompile with -fPIE
.....

我看到有一个/usr/lib/python3.8/config-3.8-x86_64-linux-gnu/libpython3.8-pic.a,并尝试链接它,但也失败了(log)。
后来我尝试了一个Docker映像(python:3.10.5-bullseye)与共享构建python,并取得了成功。
第一个
(我在最后加了-lpython3.10
它编译和./main

root@tian-B250M-Wind:/# ./main
Today is Thu Jul 14 10:39:20 2022

我为Ubuntu系统编译的python3.8 one有什么问题吗?

无论如何,我只是想验证我是否可以链接静态python库libpythonx.y.a。所以如果有人可以在新安装的机器上或使用非系统自带的python(例如,自建的静态python)来实现这一点,我愿意尝试。

okxuctiv

okxuctiv1#

问题

打印gcc -v的输出。您将在“Configured With”中找到标志--enable-default-pie。PIE(位置独立可执行文件)默认为启用。
您正在包括一个未启用PIE(python 3.8)构建的预编译对象,因此,如果您选择使用系统上安装的Python,则必须禁用PIE才能编译代码。
在Docker中没有遇到这种情况的原因是,您构建的是不同版本的预编译python 3.10,它确实启用了PIE。

溶液1

或者,将标志-no-pie添加到Makefile中的LDFlags;
或者,在编译时将-no-pie传递给gcc

溶液2

在启用PIE标志的情况下,在系统上编译所需的Python,然后使用通过PIE编译的新Python编译代码。

参考文献

https://docs.python.org/3/extending/embedding.html#very-high-level-embedding :

a7qyws3x

a7qyws3x2#

我对系统自带的python和自建的python库做了更多的实验,对于自建的python,无论是共享的还是静态的,都很容易编译成功。
对于系统自带的python,共享链接很容易,而对于静态链接,我忽略了需要链接2个额外的库-lexpat-lz。此外,系统自带的python有2种方法可以成功链接:
1.将-no-pie-lexpat -lz相加。
1.没有-no-pie,则使用libpython3.8-pic.a-lexpat -lz
检查下面的py38_system_static目标。
生成文件:

py38_system_failed:
    gcc -I/usr/include/python3.8 -I/usr/include/python3.8  -Wno-unused-result -Wsign-compare -g -fdebug-prefix-map=/build/python3.8-4wuY7n/python3.8-3.8.10=. -specs=/usr/share/dpkg/no-pie-compile.specs -fstack-protector -Wformat -Werror=format-security  -DNDEBUG -g -fwrapv -O3 -Wall -o main main.c /usr/lib/python3.8/config-3.8-x86_64-linux-gnu/libpython3.8.a -L/usr/lib/python3.8/config-3.8-x86_64-linux-gnu -L/usr/lib  -lcrypt -lpthread -ldl  -lutil -lm -lm

py38_system_shared:
    # 36K main
    gcc -I/usr/include/python3.8 -I/usr/include/python3.8  -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -o main main.c -L/usr/lib/python3.8/config-3.8-x86_64-linux-gnu -L/usr/lib -lpython3.8 -lcrypt -lpthread -ldl  -lutil -lm -lm 

py38_system_static:
    # 5.5M main 
    gcc -I/usr/include/python3.8 -I/usr/include/python3.8 -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -no-pie -O3 -Wall -o main main.c /usr/lib/python3.8/config-3.8-x86_64-linux-gnu/libpython3.8.a -L/usr/lib/python3.8/config-3.8-x86_64-linux-gnu -L/usr/lib -lcrypt -lpthread -ldl  -lutil -lm -lm -lexpat -lz
    gcc -I/usr/include/python3.8 -I/usr/include/python3.8 -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -o main main.c /usr/lib/python3.8/config-3.8-x86_64-linux-gnu/libpython3.8-pic.a -L/usr/lib/python3.8/config-3.8-x86_64-linux-gnu -L/usr/lib -lcrypt -lpthread -ldl  -lutil -lm -lm -lexpat -lz

docker_py310_share:
    # 21K main
    gcc -I/usr/local/include/python3.10 -I/usr/local/include/python3.10  -Wno-unused-result -Wsign-compare  -DNDEBUG -g -fwrapv -O3 -Wall -o main main.c -L/usr/local/lib  -lcrypt -lpthread -ldl  -lutil -lm -lm -lpython3.10

py36_static:
    # 15M main
    gcc -I/home/tian/py3.6.12_static/include/python3.6m -I/home/tian/py3.6.12_static/include/python3.6m  -Wno-unused-result -Wsign-compare  -DNDEBUG -g -fwrapv -O3 -Wall -o main main.c -L/home/tian/py3.6.12_static/lib/python3.6/config-3.6m-x86_64-linux-gnu -L/home/tian/py3.6.12_static/lib -lpython3.6m -lpthread -ldl  -lutil -lm  -Xlinker -export-dynamic

py36_shared:
    # 36K main
    gcc -I/home/tian/py3.6.12_shared/include/python3.6m -I/home/tian/py3.6.12_shared/include/python3.6m  -Wno-unused-result -Wsign-compare  -DNDEBUG -g -fwrapv -O3 -Wall -o main main.c -L/home/tian/py3.6.12_shared/lib -lpython3.6m -lpthread -ldl  -lutil -lm  -Xlinker -export-dynamic

py39_static:
    # 22M main
    gcc -I/home/tian/py3.9.13_static/include/python3.9 -I/home/tian/py3.9.13_static/include/python3.9  -Wno-unused-result -Wsign-compare  -DNDEBUG -g -fwrapv -O3 -Wall -o main main.c  -L/home/tian/py3.9.13_static/lib/python3.9/config-3.9-x86_64-linux-gnu -L/home/tian/py3.9.13_static/lib  -lpython3.9 -lcrypt -lpthread -ldl  -lutil -lm -lm 
    gcc -I/home/tian/py3.9.13_static/include/python3.9 -I/home/tian/py3.9.13_static/include/python3.9  -Wno-unused-result -Wsign-compare  -DNDEBUG -g -fwrapv -O3 -Wall -o main2 main.c /home/tian/py3.9.13_static/lib/libpython3.9.a -lcrypt -lpthread -ldl  -lutil -lm -lm 
    
py39_shared:
    # 36K main
    gcc -I/home/tian/py3.9.13_shared/include/python3.9 -I/home/tian/py3.9.13_shared/include/python3.9  -Wno-unused-result -Wsign-compare  -DNDEBUG -g -fwrapv -O3 -Wall -o main main.c -L/home/tian/py3.9.13_shared/lib  -lpython3.9 -lcrypt -lpthread -ldl  -lutil -lm -lm 

clean:
    rm main && rm main2

相关问题