Разработка расширений C и C++ на Windows
В этом разделе кратко объясняется, как создать модуль расширения Windows для Python с использованием 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 КБ. Чтобы избавиться от них, используйте диалоговое окно «Настройки проекта», вкладку «Компоновка», чтобы указать «игнорировать стандартные библиотеки». Добавьте правильную msvcrtxx.lib в список библиотек.
© 2001–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.9/extending/windows.html