5. Membangun Ekstensi C dan C++ di Windows

Bab ini menjelaskan secara singkat cara membuat modul ekstensi Windows untuk Python menggunakan Microsoft Visual C++, dan diikuti dengan informasi latar belakang yang lebih rinci tentang cara kerjanya. Materi penjelasan berguna untuk pemrogram Windows yang belajar membuat ekstensi Python dan pemrogram Unix yang tertarik untuk memproduksi perangkat lunak yang dapat dibangun di Unix dan Windows.

Penulis modul didorong untuk menggunakan pendekatan distutil untuk membangun modul ekstensi, daripada yang dijelaskan di bagian ini. Anda masih memerlukan kompiler C yang digunakan untuk membangun Python; biasanya Microsoft Visual C++.

Catatan

Bab ini menyebutkan sejumlah nama file yang menyertakan nomor versi Python yang disandikan. Nama file ini diwakili dengan nomor versi yang ditampilkan sebagai XY; dalam praktiknya, 'X' akan menjadi nomor versi utama dan 'Y' akan menjadi nomor versi minor dari rilis Python yang sedang Anda kerjakan. Misalnya, jika Anda menggunakan Python 2.2.1, XY sebenarnya akan menjadi 22.

5.1. Підхід з кулінарної книги

There are two approaches to building extension modules on Windows, just as there are on Unix: use the setuptools package to control the build process, or do things manually. The setuptools approach works well for most extensions; documentation on using setuptools to build and package extension modules is available in Building C and C++ Extensions with setuptools. If you find you really need to do things manually, it may be instructive to study the project file for the winsound standard library module.

5.2. Różnice pomiędzy Unixem a Windowsem

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; він надає вам доступ до імен спаму, але не створює окремої копії. В Unix зв’язування з бібліотекою більше схоже на імпорт спаму *; він створює окрему копію.

Turn off the implicit, #pragma-based linkage with the Python library, performed inside CPython header files.

Added in version 3.14.

5.3. Використання DLL на практиці

Windows Python побудовано на Microsoft Visual C++; використання інших компіляторів може працювати, а може і не працювати. Решта цього розділу стосується MSVC++.

When creating DLLs in Windows, you can use the CPython library in two ways:

  1. By default, inclusion of PC/pyconfig.h directly or via Python.h triggers an implicit, configure-aware link with the library. The header file chooses pythonXY_d.lib for Debug, pythonXY.lib for Release, and pythonX.lib for Release with the Limited API enabled.

    To build two DLLs, spam and ni (which uses C functions found in spam), you could use these commands:

    cl /LD /I/python/include spam.c
    cl /LD /I/python/include ni.c spam.lib
    

    The first command created three files: spam.obj, spam.dll and spam.lib. Spam.dll does not contain any Python functions (such as PyArg_ParseTuple()), but it does know how to find the Python code thanks to the implicitly linked pythonXY.lib.

    Друга команда створила ni.dll.obj і .lib), який вміє знаходити потрібні функції в спамі, а також у виконуваному файлі Python.

  2. Manually by defining Py_NO_LINK_LIB macro before including Python.h. You must pass pythonXY.lib to the linker.

    To build two DLLs, spam and ni (which uses C functions found in spam), you could use these commands:

    cl /LD /DPy_NO_LINK_LIB /I/python/include spam.c ../libs/pythonXY.lib
    cl /LD /DPy_NO_LINK_LIB /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), який вміє знаходити потрібні функції в спамі, а також у виконуваному файлі Python.

Не кожен ідентифікатор експортується до таблиці пошуку. Якщо ви хочете, щоб будь-які інші модулі (включно з Python) могли бачити ваші ідентифікатори, вам потрібно сказати _declspec(dllexport), як у void _declspec(dllexport) initspam(void) або PyObject _declspec(dllexport) *NiGetSpamData(void).

Developer Studio will throw in a lot of import libraries that you do not really need, adding about 100K to your executable. To get rid of them, use the Project Settings dialog, Link tab, to specify ignore default libraries. Add the correct msvcrtxx.lib to the list of libraries.