python - 编译官方文档 "Embedding Python in Another Application"示例失败

标签 python python-3.x linux gcc cpython

我正在尝试编译并运行来自 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;
}

来自 https://docs.python.org/3/extending/embedding.html#compiling-and-linking-under-unix-like-systems , 获取 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 ).


后来我尝试了一个带有 share build python 的 Docker 镜像(python:3.10.5-bullseye)并成功了。

root@tian-B250M-Wind:/# python3-config --cflags
-I/usr/local/include/python3.10 -I/usr/local/include/python3.10  -Wno-unused-result -Wsign-compare  -DNDEBUG -g -fwrapv -O3 -Wall
root@tian-B250M-Wind:/# python3-config --ldflags
 -L/usr/local/lib  -lcrypt -lpthread -ldl  -lutil -lm -lm
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

(我在最后加了-lpython3.10)

它编译并 ./main :

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

我编译的ubuntu系统自带的python3.8有什么问题吗?

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

最佳答案

问题

打印 gcc -v 的输出。您将在“Configured With”中找到标志 --enable-default-pie。 PIE(位置独立可执行文件)默认启用。

您包含的预编译对象不是在启用 PIE 的情况下构建的(python 3.8),因此如果您选择在系统上使用已安装的 Python,则必须禁用 PIE 才能编译您的代码。

您在 Docker 中没有遇到此问题的原因是您正在构建不同版本的预编译 python 3.10,它确实启用了 PIE。

解决方案1

要么,在 Makefile 中的 LDFlags 中添加标志 -no-pie

或者,在编译期间将 -no-pie 传递给 gcc

解决方案2

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

引用资料

https://docs.python.org/3/extending/embedding.html#very-high-level-embedding https://www.redhat.com/en/blog/position-independent-executables-pie https://linuxtut.com/en/4fc41123ed41cf443a6b/

关于python - 编译官方文档 "Embedding Python in Another Application"示例失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72979290/

相关文章:

python - 如何使用 python 检测计算机暂停?

python - 如何使用用于创建子帧的相同 groupby 调用在数据帧的子帧上应用 groupby

python - 使用 Python 的 CSV 库将数组打印为 csv 文件

python - Python 中的自定义 IDE 兼容静态类型

python3打印到字符串

linux - 创建软件设备的最佳实践?

php - MySQL : Monitor Queries

python - 如何在 Python 中检查字符串中的某个字母?

linux - 如何可靠地为用户添加或附加到 PATH

python - 为什么 python 使用 .而不是/用于导入语句中的路径?