Неопределенная ошибка символа со встроенным интерпретатором Python - PullRequest
1 голос
/ 10 марта 2020

Первоначально у меня была эта ошибка в более крупном проекте с pybind11 для встраивания интерпретатора anaconda Python. Мне удалось вывести ее и воспроизвести ошибку с помощью простого минимального примера.

Когда я запускаю свой исполняемый файл (который включает python), я получаю эту ошибку:

Traceback (most recent call last):
  File "<string>", line 3, in <module>
  File "/app/Python-3.8.2-build/lib/python3.8/struct.py", line 13, in <module>
    from _struct import *
ImportError: /app/Python-3.8.2-build/lib/python3.8/lib-dynload/_struct.cpython-38-x86_64-linux-gnu.so: undefined symbol: PyByteArray_Type

Сначала я собрал Python -3.8.2 из источника. Затем я скомпилировал исполняемый файл из следующего C кода:

#include <Python.h>

int main(int argc, char *argv[])
{
    Py_Initialize();
    PyRun_SimpleString("import struct");
    if (Py_FinalizeEx() < 0) {
        exit(120);
    }
    return 0;
}

, используя эту команду:

gcc -o execpy execpy.c \
-I/app/Python-3.8.2-build/include/python3.8 \
-Wno-unused-result -Wsign-compare  -DNDEBUG -g -fwrapv -O3 \
-L/app/Python-3.8.2-build/lib  -lcrypt -lpthread -ldl  -lutil -lm \
/app/Python-3.8.2/libpython3.8.a

Затем просто выполните ./execpy, чтобы выдать ошибку сверху ... Любой идеи?

РЕДАКТИРОВАТЬ : В этом примере я хочу статически связать libpython так же, как интерпретатор python не зависит ни от какой lib python .so.

РЕДАКТИРОВАТЬ : _struct.*.so, похоже, не имеет зависимостей от lib python, связанных в (это то же самое для моего стандартного интерпретатора anaconda python):

$ ldd /app/Python-3.8.2-build/lib/python3.8/lib-dynload/_struct.cpython-38-x86_64-linux-gnu.so
    linux-vdso.so.1 =>  (0x00007fff32bf0000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f71a5634000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f71a5266000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f71a5a5c000)

Я также проверил _struct.*.so моего системного python интерпретатора на другом компьютере, и он имеет:

    linux-vdso.so.1 =>  (0x00007ffe2b3d9000)
    libpython3.6m.so.1.0 => /lib64/libpython3.6m.so.1.0 (0x00007febe24fd000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x00007febe22e1000)
    libc.so.6 => /lib64/libc.so.6 (0x00007febe1f13000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00007febe1d0f000)
    libutil.so.1 => /lib64/libutil.so.1 (0x00007febe1b0c000)
    libm.so.6 => /lib64/libm.so.6 (0x00007febe180a000)
    /lib64/ld-linux-x86-64.so.2 (0x00007febe2c30000)

Ответы [ 2 ]

1 голос
/ 11 марта 2020

Связывание lib python статически

Краткий ответ: добавление -rdynamic к флагам заставляет меня работать.

Документация для -rdynamic флаг:

-rdynamic
    Pass the flag -export-dynamic to the ELF linker, on targets that support it. This 
    instructs the linker to add all symbols, not only used ones, to the dynamic symbol 
    table. This option is needed for some uses of dlopen or to allow obtaining 
    backtraces from within a program.

Связывание lib python динамически

Я также выяснил: если вы хотите динамически встраивать интерпретатор Python 3.8 (libpython3.8.so), с версии * произошли некоторые изменения 3.8 :

На Unix, C расширения больше не связаны с lib python, за исключением Android и Cygwin. Когда Python встроен, lib python не должен быть загружен с RTLD_LOCAL, но вместо этого RTLD_GLOBAL. Ранее, используя RTLD_LOCAL, уже не было возможности загружать C расширения, которые не были связаны с lib python, например, C расширения стандартной библиотеки, созданной разделом shared Modules / Setup , (Предоставлено Виктором Стиннером в bpo-21536.)

Также обратите внимание (см. здесь ):

Для встраивания Python в приложение новая опция --embed должна быть передана python3 -config --libs --embed, чтобы получить -l python3 .8 (связать приложение с lib python). Для поддержки как 3.8, так и более старых, попробуйте python3 -config --libs --embed first и вернуться к python3 -config --libs (без --embed), если предыдущая команда не удалась.

Add модуль pkg-config python -3.8-embed для встраивания Python в приложение: pkg-config python -3.8-embed --libs включает в себя -l python3 .8. Для поддержки версий 3.8 и более старых, попробуйте pkg-config python -XY-embed --libs first и откройте pkg-config python -XY --libs (без --embed), если предыдущая команда не выполнена (замените XY с версией Python).

Так что компиляция и связывание динамически, как это также работает для меня сейчас:

gcc -o execpy execpy.c -I/app/Python-3.8.2-build/include/python3.8 \
    -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 \
    -lcrypt -lpthread -ldl  -lutil -lm -lpython3.8\
    -L/app/Python-3.8.2-build/lib/ -Wl,-rpath,/app/Python-3.8.2-build/lib/
0 голосов
/ 10 марта 2020

Я думаю, это происходит потому, что на PyByteArray_Type нет ссылки в execpy.c, поэтому компоновщик использует значение по умолчанию --gc-sections logi c для удаления неиспользованного символа. Попробуйте добавить один из следующих параметров:

-Wl,--no-gc-sections:

Включить сбор мусора из неиспользуемых разделов ввода. Он игнорируется для целей, которые не поддерживают эту опцию. Поведение по умолчанию (не выполнение этой сборки мусора) можно восстановить, указав --no-g c -sections в командной строке. Обратите внимание, что сборка мусора для целей формата COFF и PE поддерживается, но реализация в настоящее время считается экспериментальной.

-Wl,--gc-keep-exported:

Когда --g c -sections включен, эта опция предотвращает сбор мусора из неиспользуемых входных разделов, которые содержат глобальные символы, имеющие видимость по умолчанию или защищенную видимость. Этот параметр предназначен для использования в исполняемых файлах, в которых разделы, на которые нет ссылок, в противном случае будут собираться мусором независимо от внешней видимости содержащихся символов. Обратите внимание, что этот параметр не действует при связывании общих объектов, поскольку это уже поведение по умолчанию. Эта опция поддерживается только для целей формата ELF.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...