Cython: вызов функции C выдает «неопределенный символ» - PullRequest
0 голосов
/ 07 июня 2018

Я пытаюсь использовать LMDB C API с Cython.

Я хочу импортировать следующие определения из заголовочного файла:

typedef struct MDB_env MDB_env;
int  mdb_env_create(MDB_env **env);

Итак, я создал .pxd файл:

cdef extern from 'lmdb.h':
    struct MDB_env:
        pass
    int  mdb_env_create(MDB_env **env)

И я его используюв скрипте Cython:

cdef MDB_env *e
x = mdb_env_create(&e)

Этот код прекрасно компилируется, но если я его запускаю, я получаю:

ImportError: /home/me/.cache/ipython/cython/_cython_magic_15705c11c6f56670efe6282cbabe4abc.cpython-36m-x86_64-linux-gnu.so: undefined symbol: mdb_env_create

Это происходит как в Cython .pyx + .pxdsetup и в прототипе, набранном в IPython.

Если я импортирую другой символ, скажем, константу, я могу получить к нему доступ.Кажется, я смотрю на правильный заголовочный файл.

Я не вижу различий между моим синтаксисом и документацией, но я явно что-то делаю не так.Может кто-нибудь дать мне подсказку?

Спасибо.

1 Ответ

0 голосов
/ 07 июня 2018

Чтобы скомпилировать его с помощью IPythons-magic (было бы неплохо, если бы вы прямо упомянули об этом в своем вопросе), вам необходимо указать путь к библиотеке (через -L -опцию) и имя библиотеки (через -l -опцию) встроенной c-библиотеки, которую вы хотите обернуть, см. также документацию :

%%cython  -L=<path to your library> -l=<your_library>

Библиотека, которую вы пытаетесь обернуть, не только для заголовкабиблиотека.Это означает, что некоторые символы (например, mdb_env_create) только объявлены, но не определены в заголовке.Когда вы создаете библиотеку, определения этих символов можно найти в результирующем артефакте, который должен быть предоставлен компоновщику при сборке вашего расширения.Эти определения необходимы для запуска программы.

Если вы этого не сделаете, в Linux произойдет следующее: Когда построено расширение (*.so -файл), компоновщик допускает неопределенные символыпо умолчанию - так что этот шаг является «успешным» - но ошибка только откладывается.Когда расширение загружается через import, Python загружает соответствующий *.so с помощью ldopen, и на этом этапе загрузчик проверяет, что определения всех символов известны.Но мы не предоставили определение mdb_env_create, поэтому загрузчик завершился ошибкой с

неопределенным символом: mdb_env_create

Это другое для символов, которые определены взаголовочный файл, например, перечисления MDB_FIRST & Co - скомпилированная библиотека не нужна, и, следовательно, расширение может быть загружено, так как нет неопределенных символов.

...