Cython: вызов функции C выдает "неопределенный символ"

Я пытаюсь использовать 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 + .pxd настройки и в прототипе набраны в IPython.

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

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

Благодарю.

1 ответ

Решение

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

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

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

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

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

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

Другие вопросы по тегам