Создание расширений C и C++ на Windows
В данном разделе кратко объясняется, как создать модуль расширения для Python на Windows с использованием Microsoft Visual C++, а затем приводится более подробная информация о его работе. Эта информация полезна как программистам Windows, изучающим создание расширений Python, так и программистам Unix, заинтересованным в разработке программного обеспечения, которое можно успешно собрать как на Unix, так и на Windows.
Авторам модулей рекомендуется использовать подход distutils для сборки модулей расширения вместо описанного в данном разделе. Вам всё равно потребуется компилятор C, который использовался для сборки Python; обычно это Microsoft Visual C++.
Примечание
В данном разделе упоминаются несколько имен файлов, содержащих закодированный номер версии Python. Эти имена файлов представлены с номером версии, показанным как XY; на практике 'X' будет основной версией, а 'Y' — второстепенной версией выпуска Python, с которым вы работаете. Например, если вы используете Python 2.2.1, XY фактически будет 22.
5.1. Рецептурный подход
Существует два подхода к сборке модулей расширения на Windows, как и на Unix: использовать пакет distutils для управления процессом сборки или выполнять действия вручную. Подход distutils хорошо подходит для большинства расширений; документация по использованию distutils для сборки и упаковки модулей расширения доступна в Распространение модулей Python (старая версия). Если вы обнаружите, что вам действительно необходимо выполнять действия вручную, изучите файл проекта для модуля стандартной библиотеки winsound.
5.2. Отличия между Unix и Windows
Unix и Windows используют совершенно разные парадигмы для загрузки кода во время выполнения. Прежде чем пытаться создать модуль, который можно динамически загрузить, ознакомьтесь с принципами работы вашей системы.
В Unix файл совместно используемого объекта (.so) содержит код, который будет использоваться программой, а также имена функций и данных, которые он ожидает найти в программе. При объединении файла с программой все ссылки на эти функции и данные в коде файла изменяются таким образом, чтобы указывать на фактические места в памяти программы, где размещаются функции и данные. Это в основном операция связывания.
В Windows файл динамически подключаемой библиотеки (.dll) не содержит ни одной висячей ссылки. Вместо этого доступ к функциям или данным осуществляется через таблицу поиска. Таким образом, код DLL не должен исправляться во время выполнения, чтобы ссылаться на память программы; вместо этого код уже использует таблицу поиска DLL, а таблица поиска изменяется во время выполнения, чтобы указывать на функции и данные.
В Unix существует только один тип файла библиотеки (.a), который содержит код из нескольких объектных файлов (.o). Во время этапа связывания для создания файла совместно используемого объекта (.so) компоновщик может обнаружить, что не знает, где определен идентификатор. Компоновщик будет искать его в объектных файлах в библиотеках; если он найдет его, он включит весь код из этого объектного файла.
В Windows есть два типа библиотек: статическая библиотека и библиотека импорта (обе называются .lib). Статическая библиотека похожа на файл Unix .a; она содержит код, который необходимо включать по мере необходимости. Библиотека импорта используется в основном для подтверждения компоновщику, что определённый идентификатор корректен и будет присутствовать в программе при загрузке DLL. Таким образом, компоновщик использует информацию из библиотеки импорта для построения таблицы поиска для использования идентификаторов, которые не включены в DLL. Когда приложение или DLL связываются, может быть сгенерирована библиотека импорта, которая потребуется для всех будущих DLL, зависящих от символов в приложении или DLL.
Предположим, что вы создаёте два модуля динамической загрузки, B и C, которые должны использовать другой блок кода A. В Unix вы не передавали бы A.a компоновщику для B.so и C.so; это привело бы к его включению дважды, так что B и C имели бы по своей копии. В Windows при создании A.dll также создаётся A.lib. Вы должны передавать A.lib компоновщику для B и C. A.lib не содержит кода; она содержит только информацию, которая будет использоваться во время выполнения для доступа к коду A.
В Windows использование библиотеки импорта похоже на использование import spam; оно даёт вам доступ к именам spam, но не создаёт отдельную копию. В Unix связывание с библиотекой больше похоже на from spam import *; оно создаёт отдельную копию.
5.3. Использование DLL на практике
Windows Python построен с использованием Microsoft Visual C++; использование других компиляторов может или не может работать. Остальная часть этого раздела специфична для MSVC++.
При создании DLL в Windows необходимо передать pythonXY.lib компоновщику. Чтобы создать две DLL, spam и ni (которая использует функции C, найденные в spam), вы могли бы использовать следующие команды:
cl /LD /I/python/include spam.c ../libs/pythonXY.lib cl /LD /I/python/include ni.c spam.lib ../libs/pythonXY.lib
Первая команда создала три файла: spam.obj, spam.dll и spam.lib. Spam.dll не содержит никаких функций Python (таких как PyArg_ParseTuple()), но она знает, как найти код Python благодаря pythonXY.lib.
Вторая команда создала ni.dll (и .obj и .lib), которая знает, как найти необходимые функции из spam, а также из исполняемого файла Python.
Не каждый идентификатор экспортируется в таблицу поиска. Если вы хотите, чтобы другие модули (включая Python) могли видеть ваши идентификаторы, вам нужно указать _declspec(dllexport), как в void _declspec(dllexport) initspam(void) или PyObject _declspec(dllexport) *NiGetSpamData(void).
Developer Studio добавит много библиотек импорта, которые вам на самом деле не нужны, увеличивая размер вашего исполняемого файла примерно на 100 КБ. Чтобы избавиться от них, используйте диалог «Параметры проекта», вкладку «Связывание», чтобы указать ignore default libraries. Добавьте правильную msvcrtxx.lib в список библиотек.
© 2001–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.11/extending/windows.html