Создание исполняемого файла на Cython

Играл с Cython. Обычно программируют на Python, но использовали C в предыдущей жизни. Я не могу понять, как сделать отдельно стоящий исполняемый файл.

Я скачал cython и могу создать файл.pyx (это просто обычный файл Python с расширением.pyx), который выполняется в оболочке Python, используя: import pyximport; pyximport.install()

Я могу сгенерировать файл.c в командной строке с помощью: cython file.pyx. Я могу сгенерировать файл.so, создав стандартный файл setup.py и выполнив:

setup.py build_ext --inplace

Я пытался сделать исполняемый файл из файла.so с помощью gcc с различными параметрами, но всегда имел массу пропущенных файлов, заголовков и т. Д. Пробовал указывать на заголовки практически везде, но безуспешно, и я не очень знаком с тем, что делают все параметры gcc, или даже если я должен использовать gcc.

У меня возникло отключение из-за того, что я могу запускать свою программу в оболочке Python, но не в командной строке (я не хочу, чтобы пользователи приходили в оболочку, импортировали модули и т. Д.).

Что мне здесь не хватает?

4 ответа

Решение

То, что вы хотите, это --embed флаг для компилятора Cython. Там нет тонны документации, но это то, что я смог найти. Это ссылка на простой рабочий пример.

Чтобы скомпилировать исходный код Cython в файл C, который затем можно скомпилировать в исполняемый файл, вы используете команду типа cython myfile.pyx --embed и затем скомпилируйте с любым C-компилятором, который вы используете.

Когда вы компилируете исходный код на C, вам все равно нужно будет включить каталог с заголовками Python и ссылку на соответствующую разделяемую библиотеку Python в вашей системе (файл с именем что-то вроде libpython27.so или же libpython27.a если вы используете Python 2.7).

Изменить: Вот еще несколько инструкций о том, как получить команды для включения правильных заголовков и ссылки на соответствующие библиотеки.

Как я уже говорил ранее, вам нужно запустить компилятор Cython следующим образом:

cython <cython_file> --embed

Чтобы скомпилировать с помощью gcc, вам нужно найти, где находятся заголовки python в вашей системе (вы можете получить это местоположение, запустив distutils.sysconfig.get_python_inc() (вам придется импортировать его первым). Это, вероятно, просто /include подкаталог в вашем каталоге установки Python.

Вам также нужно будет найти общую библиотеку Python. Для Python 2.7 это будет libpython27.a в Windows или libpython2.7.so в линуксе

Ваша команда gcc будет тогда

gcc <C_file_from_cython> -I<include_directory> -L<directory_containing_libpython> -l<name_of_libpython_without_lib_on_the_front> -o <output_file_name>

Может быть целесообразно включить -fPIC флаг. На 64-битных компьютерах с Windows вы также должны будете включить флаги -D MS_WIN64 это говорит MINGW, чтобы скомпилировать для 64-битных окон.

Если вы компилируете что-то, что зависит от NumPy, вам также нужно будет включить каталог, содержащий заголовки NumPy. Вы можете найти эту папку, запустив numpy.get_include() (опять же после импорта numpy). Ваша команда GCC становится

gcc <C_file_from_cython> -I<include_directory> -I<numpy_include_directory> -L<directory_containing_libpython> -l<name_of_libpython_without_lib_on_the_front> -o <output_file_name>

Это руководство по опциям команды gcc может быть полезным.

Кроме того, я бы порекомендовал вам использовать представления памяти Cython, если это возможно. Это позволит вам не включать заголовки NumPy и включать файл pxd NumPy в файл Cython. Это также упрощает оптимизацию операций нарезки для компилятора C.

Протестировал это на Ubuntu:

устанавливать Cython используя следующее (Python 2):

sudo apt-get install cython

Для Python 3:

sudo apt-get install cython3

Чтобы скомпилировать код Python в код на C, запустите cython в cython3 для Python 3):

cython --embed -o example.c example.py

Это сгенерирует example.c файл.

Теперь скомпилируйте example.c файл:

gcc -Os -I /usr/include/python2.7 example.c -lpython2.7 -o example

Запустите файл:

./example

Теперь для Python 3 что-то вроде этого будет работать (не проверено):

gcc -Os -I /usr/include/python3.6 example.c -lpython3.6 -o example

где python3.x версия Python, установленная на вашем компьютере

Это решение для Windows + MS Visual Studio 14 (поскольку никто не упомянул cl.exe параметров пока нет).

Сначала используйте embed параметр для получения test.c файл:

cython test.pyx --embed

Затем скомпилируйте его:

call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64
cl test.c /I C:\Python37\include /link C:\Python37\libs\python37.lib

На выходе получается небольшой исполняемый файл. test.exe (140 КБ в моем случае для print("Hello World")).

Заметки:

Основываясь на ответе Рафаэля, вот объяснение того, как сделать исполняемый файл «Hello, World» с помощью Cython и Python 3 (проверено на Termux), а затем инструкции для Python 2:

cython3похоже, это не вариант для моей системы, поэтому вместо этого я делаю следующее:

Файл называется test.py:

      print("Hello, world!")

Затем сделайте следующее:

      cython -3 --embed -o test.c test.py

Затем вам нужно выяснить, какой путь включения вам нужен, и, возможно, ваши библиотеки.

Я использую Python 3.10.6; поэтому я использую программу python3.10-config для получения информации перед ее вводом в gcc:

      python3.10-config --includes

Для меня это выводит это:

      -I/data/data/com.termux/files/usr/include/python3.10 -I/data/data/com.termux/files/usr/include/python3.10

Он дал мне один и тот же путь дважды (я не знаю почему), так что просто используйте этот путь (я думаю, вам нужно использовать его только один раз).

Тогда сделайте

      python3.10-config --libs

Для меня это выводит это:

      -lpython3.10 -lcrypt -ldl  -lm -lm

Я не уверен, что каждый из них важен для каждой программы, так как «Hello, world» работает, если я только поставлю-lpython3.10.

Во всяком случае, тогда я делаю это, и это дает мне исполняемый файл:

      gcc -Os -I/data/data/com.termux/files/usr/include/python3.10 test.c -lpython3.10 -o test

Также есть программа под названием python2.7-config.

Если я хочу получить исполняемый файл с Python 2.7.18, я могу сделать это вместо вышеописанного:

      cython -2 --embed -o test.c test.py

Затем

      python2.7-config --includes
python2.7-config --libs

Это дает мне это:

  • -I/data/data/com.termux/files/usr/include/python2.7 -I/data/data/com.termux/files/usr/include/python2.7
  • -lpython2.7 -ldl -lm

Наконец, я делаю это, чтобы получить исполняемый файл:

      gcc -Os -I/data/data/com.termux/files/usr/include/python2.7 test.c -lpython2.7 -o test
Другие вопросы по тегам