Загрузка против ссылок в модулях Cython - PullRequest
0 голосов
/ 29 сентября 2019

Исследуя шаги компиляции Cython, я обнаружил, что мне нужно явно связать библиотеки C, например, math, в setup.py.Тем не менее, такой шаг не был нужен для NumPy.Почему так?Импортируется ли numpy через обычный механизм импорта python?Если это так, нам не нужно явно ссылаться на какой-либо модуль расширения в Cython?

Я пытался порыться в официальной документации, но, к сожалению, не было никакого объяснения того, когда явная ссылкатребуется и когда это будет сделано автоматически.

1 Ответ

0 голосов
/ 30 сентября 2019

Вызов функции cdef соответствует более или менее просто переходу к адресу в памяти - той, с которой команда должна быть прочитана / выполнена.Вопрос в том, как этот адрес предоставляется.Есть несколько случаев, которые нам нужно рассмотреть:

A. встроенные функции

Код этих функций либо встроенный, либо определение функции в том же переводеединицы, таким образом, адрес известен компоновщику во время соединения - нет необходимости в дополнительных библиотеках.

Примером являются библиотеки только для заголовков.

Последствия: Ничегоэто должно быть сделано в setup.py.

B. статическое связывание

Определение / функциональность, которые нам нужны, находятся в другом модуле / библиотеке перевода - целевой-адресПереход вычисляется во время соединения и больше не может быть изменен впоследствии.

Примером являются дополнительные c / cpp-файлы или статические библиотеки, которые добавляются в определение расширения.

Последствия: Статическая библиотека должна быть добавлена ​​к setup.py, то есть путь к библиотеке и имя библиотеки.

C. динамическое связывание

Предоставлена ​​предоставленная функциональностьв общем объекте / dll.Адрес для перехода вычисляется во время выполнения из загрузчика и может быть заменен при запуске программы путем обмена загруженными общими объектами.

В качестве примера можно привести stdlibc ++ (обычно добавляемый автоматически g ++) или libm, который не является автоматическидобавлено в команду компоновщика с помощью gcc.

Последствия: Динамическая библиотека должна быть добавлена ​​к setup.py, то есть путь к библиотеке и имя библиотеки, возможно, r-путь.поэтому / DLL должен быть предоставлен во время выполнения.В этом SO-посте можно найти гораздо больше информации о Cython / Python с использованием динамических библиотек.

D. Вызов через указатель

Линкер необходим только тогда, когда мы вызываемфункция через свое имя.Если мы вызываем его через указатель на функцию, нам не нужен компоновщик / загрузчик, потому что адрес функции уже известен - значение в указателе функции.

Пример: генерируемые Cython модули используют этомеханизм, обеспечивающий доступ к его функциям cdef, экспортированным через pxd -файл.Он создает структуру данных (которая хранится в виде переменной __pyx_capi__ в самом модуле) указателей на функции, которая заполняется загрузчиком после загрузки so / dll.

Мы можем ожидать, что дляпример

#foo.pyx:
cdef void doit():
    print("doit")
#foo.pxd
cdef void doit()

>>> cythonize -3 -i foo.pyx
>>> python -c "import foo; print(foo.__pyx_capi__)" 
{'doit': <capsule object "void (void)" at 0x7f7b10bb16c0>}

Теперь, вызов функции cdef из другого модуля просто переходит на соответствующий адрес.

Последствия: Нам нужно импортировать необходимую функциональность.


Тем не менее, теперь, после того, как все это написали, я понимаю, что numpy - это не один из вышеперечисленных случаев (я всегда предполагал, что это смесь A и D, но больше не уверен)- скоро обновлю ответ относительно numpy.

...