Spec-Zone.ru › Python 3.8

Построение расширений C и C++

Расширение C для CPython — это общая библиотека (например, файл .so в Linux, .pyd в Windows), экспортирующая функцию инициализации.

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

Функция инициализации имеет следующий вид:

PyObject* PyInit_modulename(void)

Она возвращает либо полностью инициализированный модуль, либо экземпляр PyModuleDef. Подробнее см. Инициализация модулей C.

Для модулей с именами, состоящими только из символов ASCII, функция должна называться PyInit_<modulename>, где <modulename> заменяется именем модуля. При использовании Многофазной инициализации разрешены имена модулей, содержащие не только символы ASCII. В этом случае имя функции инициализации — PyInitU_<modulename>, где имя модуля <modulename> закодировано с помощью кодировки punycode Python, а дефисы заменены на подчеркивания. В Python:

def initfunc_name(name):
    try:
        suffix = b'_' + name.encode('ascii')
    except UnicodeEncodeError:
        suffix = b'U_' + name.encode('punycode').replace(b'-', b'_')
    return b'PyInit' + suffix

Можно экспортировать несколько модулей из одной общей библиотеки, определив несколько функций инициализации. Однако для их импорта необходимо использовать символические ссылки или пользовательский импортер, так как по умолчанию обнаруживается только функция, соответствующая имени файла. Подробнее см. раздел «Несколько модулей в одной библиотеке» в PEP 489.

4.1. Построение расширений C и C++ с помощью distutils

Модули расширений можно создавать с помощью distutils, который включён в Python. Поскольку distutils также поддерживает создание бинарных пакетов, пользователям не обязательно нужен компилятор и distutils для установки расширения.

Пакет distutils содержит скрипт-драйвер setup.py. Это обычный Python-файл, который в самом простом случае может выглядеть так:

from distutils.core import setup, Extension

module1 = Extension('demo',
                    sources = ['demo.c'])

setup (name = 'PackageName',
       version = '1.0',
       description = 'This is a demo package',
       ext_modules = [module1])

С этим setup.py, и файлом demo.c, выполнение команды

python setup.py build

скомпилирует demo.c, и создаст модуль расширения demo в директории build. В зависимости от системы, файл модуля окажется в поддиректории build/lib.system, и может иметь имя demo.so или demo.pyd.

В setup.py, все выполнение осуществляется вызовом функции setup. Она принимает переменное число ключевых аргументов, из которых в примере выше используется только подмножество. В частности, в примере указана метаинформация для сборки пакетов и содержимое пакета. Обычно пакет содержит дополнительные модули, такие как Python-модули, документацию, подпакеты и т.д. Подробнее о функциях distutils см. документацию distutils по адресу Распространение Python-модулей (старая версия); в данном разделе рассматривается только построение модулей расширений.

Часто аргументы к setup() предварительно вычисляются для лучшей структуры скрипта-драйвера. В примере выше аргумент ext_modules функции setup() — список модулей расширения, каждый из которых является экземпляром Extension. В примере экземпляр определяет расширение demo, которое создаётся путём компиляции единственного исходного файла demo.c.

Во многих случаях построение расширения является более сложным, так как могут потребоваться дополнительные препроцессорные определения и библиотеки. Это показано в примере ниже.

from distutils.core import setup, Extension

module1 = Extension('demo',
                    define_macros = [('MAJOR_VERSION', '1'),
                                     ('MINOR_VERSION', '0')],
                    include_dirs = ['/usr/local/include'],
                    libraries = ['tcl83'],
                    library_dirs = ['/usr/local/lib'],
                    sources = ['demo.c'])

setup (name = 'PackageName',
       version = '1.0',
       description = 'This is a demo package',
       author = 'Martin v. Loewis',
       author_email = 'martin@v.loewis.de',
       url = 'https://docs.python.org/extending/building',
       long_description = '''
This is really just a demo package.
''',
       ext_modules = [module1])

В этом примере функция setup() вызывается с дополнительной метаинформацией, что рекомендуется, когда необходимо собрать пакеты для распространения. Для самого расширения она указывает препроцессорные определения, директории заголовочных файлов, директории библиотек и библиотеки. В зависимости от компилятора, distutils передаёт эту информацию компилятору различными способами. Например, в Unix это может привести к командам компиляции

gcc -DNDEBUG -g -O3 -Wall -Wstrict-prototypes -fPIC -DMAJOR_VERSION=1 -DMINOR_VERSION=0 -I/usr/local/include -I/usr/local/include/python2.2 -c demo.c -o build/temp.linux-i686-2.2/demo.o

gcc -shared build/temp.linux-i686-2.2/demo.o -L/usr/local/lib -ltcl83 -o build/lib.linux-i686-2.2/demo.so

Эти строки приведены только для демонстрации; пользователи distutils должны доверять, что distutils правильно формирует вызовы.

4.2. Распространение модулей расширения

После успешного построения расширения можно использовать его тремя способами.

Конечные пользователи обычно хотят установить модуль, для этого они выполняют

python setup.py install

Авторы модулей должны создавать пакеты исходного кода; для этого они выполняют

python setup.py sdist

В некоторых случаях дополнительные файлы необходимо включать в пакет исходного кода; это делается через файл MANIFEST.in; подробнее см. Указание файлов для распространения.

Если пакет исходного кода был собран успешно, авторы могут также создать бинарные дистрибутивы. В зависимости от платформы можно использовать одну из следующих команд.

python setup.py bdist_wininst
python setup.py bdist_rpm
python setup.py bdist_dumb

© 2001–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.8/extending/building.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API