Динамическая библиотека C++ в Python
Создать динамическую библиотеку на одном языке (С++) и использовать её в другом (Python). На C++ написать динамическую библиотеку, которая содержит в себе вычислители нескольких математических функций (функции принимают коэффициенты в качестве параметров и возвращают массив точек с некоторым шагом); на Python, используя pylib, написать программу, которая строит графики функций, вычисленных в динамической библиотеке.
Собственно не знаю как сделать импорт библиотеке из C++ в Python, помогите пожалуйста с реализацией.
Отслеживать
52.2k 11 11 золотых знаков 108 108 серебряных знаков 312 312 бронзовых знаков
задан 17 окт 2017 в 3:50
user270842 user270842
11 1 1 серебряный знак 2 2 бронзовых знака
У вас проблема только с импортом? Импортирование динамической библиотеки аналогично обычному модулю.
17 окт 2017 в 6:25
Модуль ctypes еще можно использовать. В чем проблема у вас — непонятно.
17 окт 2017 в 7:15
boost::python спасет мир
17 окт 2017 в 7:32
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Чтобы напрямую использовать dll из Питона, существуют ctypes , cffi модули.
К примеру, чтобы вызвать printf() функцию из стандартной Си библиотеки напрямую:
#!/usr/bin/env python import ctypes from ctypes.util import find_library try: libc = ctypes.cdll.msvcrt # Windows, load msvcrt.dll except OSError: libc = ctypes.cdll.LoadLibrary(find_library('c')) # load libc.so.6 n = libc.printf(b"abc ") libc.printf(b"%d\n", n)
Чтобы вызвать C++ функцию, её следует экспортировать как extern «C» :
extern "C" int f(int n, double* points);
В более сложных случаях можно Cython использовать, чтобы обернуть C++ библиотеку, предоставляя идиоматический Питон интерфейс остальному коду. Существует множество других библиотек, которые помогают связывать Python и С/C++ код в разных ситуациях.
Создание расширения C++ для Python
Область применения:Visual Studio Visual Studio для Mac
Visual Studio Code ![]()
Модули, написанные на C++ (или C), обычно используются для расширения возможностей интерпретатора Python. Они также обеспечивают доступ к низкоуровневым возможностям операционной системы.
Модули можно разделить на три следующих основных типа.
- Модули ускорения. Так как Python является интерпретируемым языком, вы можете писать модули ускорителя на C++ для повышения производительности.
- Модули-оболочки. Эти модули открывают существующие интерфейсы C/C++ для кода Python или предоставляют адаптированный API, который удобно использовать в Python.
- Модули низкоуровневого системного доступа. Эти модули создаются для доступа к низкоуровневым функциям среды выполнения CPython , операционной системы или базового оборудования.
В этой статье рассматривается создание модуля расширения C++ для CPython , который вычисляет гиперболический тангенс и вызывает его из кода Python. Подпрограмма реализована сначала на языке Python, чтобы продемонстрировать относительный прирост производительности по сравнению с реализацией той же подпрограммы на C++.
В этой статье также показаны два способа сделать расширение C++ доступным в Python:
- использование стандартных расширений CPython , как описано в документации по Python;
- использование PyBind11 (рекомендуется для C++ 11 благодаря его простоте). Для обеспечения совместимости используйте какую-то из более актуальных версий Python.
Полный пример из этого руководства см. на GitHub по ссылке python-samples-vs-cpp-extension.
Необходимые компоненты

- Visual Studio 2017 или более поздней версии с установленной рабочей нагрузкой разработки на Python. Эта рабочая нагрузка включает встроенные средства разработки Python, которые подключают рабочую нагрузку C++ и наборы инструментов, необходимые для собственных расширений.
Примечание. При установке рабочей нагрузки Приложения для обработки и анализа данных и аналитические приложения среда Python и встроенные средства разработки Python устанавливаются по умолчанию.
Дополнительные сведения о параметрах установки см. в разделе Установка поддержки Python в Visual Studio. Если вы устанавливаете Python отдельно, обязательно выберите параметр Скачать отладочные символы в разделе Дополнительные параметры установщика. Этот параметр необходим, чтобы вы могли использовать отладку в смешанном режиме между кодом Python и машинным кодом.
Создание приложения Python
- Создайте проект Python в Visual Studio, выбрав Файл>Создать>Проект.
- Выполните поиск по ключевому слову Python, выберите шаблон Приложение Python, задайте имя и расположение, а затем нажмите кнопку OK.
- В файл проекта с расширением .py вставьте следующий код. Чтобы испытать некоторые функции редактирования Python, попробуйте ввести этот код вручную. Этот код вычислит гиперболический тангенс без использования математической библиотеки, что позволит вам ускорить работу встроенных расширений.
Совет Сначала напишите код только на Python, а затем перепишите его на C++. Таким образом вам будет проще проверить правильность машинного кода.
from random import random from time import perf_counter COUNT = 500000 # Change this value depending on the speed of your computer DATA = [(random() - 0.5) * 3 for _ in range(COUNT)] e = 2.7182818284590452353602874713527 def sinh(x): return (1 - (e ** (-2 * x))) / (2 * (e ** -x)) def cosh(x): return (1 + (e ** (-2 * x))) / (2 * (e ** -x)) def tanh(x): tanh_x = sinh(x) / cosh(x) return tanh_x def test(fn, name): start = perf_counter() result = fn(DATA) duration = perf_counter() - start print('<> took seconds\n\n'.format(name, duration)) for d in result: assert -1 '.format(COUNT)) test(lambda d: [tanh(x) for x in d], '[tanh(x) for x in d] (Python implementation)')
Совет При запуске тестов производительности всегда выбирайте в меню Отладка>Запуск без отладки. Это помогает избежать дополнительных временных затрат, возникающих при запуске кода в отладчике Visual Studio.
Создание основных проектов C++
Следуйте инструкциям в этом разделе, чтобы создать два идентичных проекта C++ с именами superfastcode и superfastcode2. Позднее вы будете использовать в этих проектах разные способы предоставления кода C++ в Python.
- В обозревателе решений щелкните решение правой кнопкой мыши и последовательно выберите пункты Добавить>Новый проект. Решение Visual Studio может одновременно содержать проекты Python и C++ — это одно из преимуществ использования Visual Studio для Python.
- Выполните поиск C++, выберите Пустой проект, укажите либо superfastcode для первого проекта, либо superfastcode2 для второго проекта, а затем нажмите кнопку OK.
Совет Или, если вы установили собственные средства разработки Python в Visual Studio, можете начать с шаблона «Модуль расширения Python». В этом шаблоне уже имеется большая часть описанных здесь возможностей. Но в этом пошаговом руководстве начало работы с пустого проекта позволяет шаг за шагом продемонстрировать создание модуля расширения. Ознакомившись с процессом, в дальнейшем вы сможете использовать этот шаблон для экономии времени при написании собственных расширений.
Важно! Файл с расширением .cpp нужен, чтобы активировать страницы свойств C++ в последующих шагах.
- Для 64-разрядной среды выполнения Python активируйте конфигурацию x64.
- Для 32-разрядной среды выполнения Python следует активировать конфигурацию Win32.
Примечание. При создании собственных проектов вам понадобится настроить конфигурации и отладки, и выпуска. В этом уроке вы настроите только конфигурацию отладки и установите в ней использование сборки выпуска CPython. Эта конфигурация отключает некоторые функции отладки среды выполнения C++, в том числе утверждения. Для использования двоичных файлов отладки CPython (python_d.exe) требуются другие параметры.
Примечание. Если вы не видите вкладку C/C++ в свойствах проекта, значит, в проекте нет файлов, определенных как исходные файлы C/C++. Такая ситуация может возникнуть, если вы создали исходный файл без расширения .c или .cpp. Например, если в диалоговом окне создания элемента вы случайно введете module.coo вместо module.cpp, Visual Studio создаст файл, но не задаст для него тип Код C/C, что требуется для активации вкладки свойств C/C++. Такая неправильная идентификация сохранится, даже если вы переименуете файл и добавите расширение .cpp. Чтобы установить правильный тип файла, в Обозревателе решений щелкните файл правой кнопкой мыши и выберите пункт Свойства. Затем в качестве типа файлавыберите Код C/C++.
#include #include const double e = 2.7182818284590452353602874713527; double sinh_impl(double x) < return (1 - pow(e, (-2 * x))) / (2 * pow(e, -x)); >double cosh_impl(double x) < return (1 + pow(e, (-2 * x))) / (2 * pow(e, -x)); >double tanh_impl(double x) < return sinh_impl(x) / cosh_impl(x); >
Преобразование проекта C++ в расширения для Python
Чтобы преобразовать DLL-библиотеку C++ в расширение для Python, сначала нужно изменить экспортируемые методы для взаимодействия с типами Python. После этого добавьте функцию, экспортирующую модуль, а также определения методов модуля.
В последующих разделах объясняется, как выполнить эти действия с помощью расширений CPython и PyBind11.
Использование расширений CPython
Дополнительные сведения о коде, приведенном в этом разделе, см. в справочном руководстве по API Python/C, в частности на странице Объекты модуля. Не забудьте выбрать версию Python в раскрывающемся списке в правом верхнем углу.
-
В верхней части файла module.cpp включите Python.h.
#include
PyObject* tanh_impl(PyObject* /* unused module reference */, PyObject* o) < double x = PyFloat_AsDouble(o); double tanh_x = sinh_impl(x) / cosh_impl(x); return PyFloat_FromDouble(tanh_x); >
static PyMethodDef superfastcode_methods[] = < // The first property is the name exposed to Python, fast_tanh // The second is the C++ function with the implementation // METH_O means it takes a single PyObject argument < "fast_tanh", (PyCFunction)tanh_impl, METH_O, nullptr >, // Terminate the array with an object containing nulls. < nullptr, nullptr, 0, nullptr >>;
static PyModuleDef superfastcode_module = < PyModuleDef_HEAD_INIT, "superfastcode", // Module name to use with Python import statements "Provides some functions, but faster", // Module description 0, superfastcode_methods // Structure that defines the methods of the module >;
PyMODINIT_FUNC PyInit_superfastcode()
Использование PyBind11
Если вы выполнили действия из предыдущего раздела, вы наверняка заметили, что использовали много стандартного кода для создания необходимых структур модулей для кода C++. PyBind11 упрощает этот процесс с помощью макросов в файле заголовка C++, которые позволяют получить тот же результат с гораздо меньшим объемом кода.
Дополнительные сведения о коде в этом разделе см. в разделе Основы PyBind11.
- Установите PyBind11 с помощью pip: pip install pybind11 или py -m pip install pybind11 . Вы также можете установить PyBind11 с помощью окна «Окружения Python», а затем использовать его команду Открыть в PowerShell для выполнения следующего шага.
- В том же терминале выполните python -m pybind11 —includes или py -m pybind11 —includes . Это действие выводит список путей, которые следует добавить в свойство C/C++>Общие>Дополнительные каталоги включаемых файлов вашего проекта. Обязательно удалите префикс -I , если он присутствует.
- В верхнюю часть нового файла module.cpp, который не содержит изменения из предыдущего раздела, включите pybind11.h.
#include
namespace py = pybind11; PYBIND11_MODULE(superfastcode2, m)
Устранение ошибок компиляции
Модуль C++ может не компилироваться по следующим причинам.
- Ошибка: не удается обнаружить Python.h (E1696: не удается открыть исходный файл Python.h и/или C1083: не удается открыть включаемый файл: Python.h — не существует такого файла или каталога) Решение: проверьте, что путь в разделе C/C++>Общие>Дополнительные каталоги включаемых файлов в свойствах проекта указывает на папку include установки Python. См. шаг 6 в разделе Создание основного проекта C++. Дополнительные сведения о доступе к сведениям о конфигурации установки Python см . в документации по Python.
- Ошибка: не удается обнаружить библиотеки Python Решение: проверьте, что путь в разделе Компоновщик>Общие>Дополнительные каталоги библиотек в свойствах проекта указывает на папку libs установки Python. См. шаг 6 в разделе Создание основного проекта C++. Дополнительные сведения о доступе к сведениям о конфигурации установки Python см . в документации по Python.
- Ошибки компоновщика, связанные с решением целевой архитектуры: измените архитектуру проекта целевого объекта C++ на соответствие архитектуре установки Python. Например, если вы хотите использовать в проекте C++ версию Win32, но у вас установлена версия Python x64, измените проект C++ для работы с версией х64.
Тестирование кода и сравнение результатов
Теперь, когда библиотека DLL структурирована как расширения Python, можно ссылаться на них из проекта Python, импортировать модули и использовать их методы.
Предоставление доступа к библиотеке DLL для Python
Библиотеку DLL можно сделать доступной для Python несколькими способами. Покажем два метода, которые рекомендуется рассмотреть.

- Первый метод работает, если проект Python и проект C++ находятся в одном решении. Выполните следующие действия.
- В Обозревателе решений щелкните правой кнопкой мыши узел Ссылки в вашем проекте Python, а затем выберите команду Добавить ссылку.
- В открывшемся диалоговом окне перейдите на вкладку Проекты, выберите проекты superfastcode и superfastcode2 и нажмите кнопку OK.
- В другом методе устанавливается модуль в вашей среде Python, что делает этот модуль доступным и для других проектов Python. Дополнительные сведения см. в документации по проекту setuptools. Выполните следующие действия.
- Создайте в проекте C++ файл с именем setup.py, щелкнув проект правой кнопкой мыши и выбрав пункт Добавить>Новый элемент.
- Выберите Файл C++ (. cpp), назначьте этому файлу имя setup.py и нажмите кнопку OK. Если файлу назначить имя с расширением .py, это позволяет Visual Studio распознать его как файл Python, несмотря на использование шаблона файла C++. Когда файл откроется в редакторе, вставьте в него следующий код в зависимости от метода расширения. Для расширений CPython (проект superfastcode)
from setuptools import setup, Extension sfc_module = Extension('superfastcode', sources = ['module.cpp']) setup( name='superfastcode', version='1.0', description='Python Package with superfastcode C++ extension', ext_modules=[sfc_module] )
Для PyBind11 (проект superfastcode2)
from setuptools import setup, Extension import pybind11 cpp_args = ['-std=c++11', '-stdlib=libc++', '-mmacosx-version-min=10.7'] sfc_module = Extension( 'superfastcode2', sources=['module.cpp'], include_dirs=[pybind11.get_include()], language='c++', extra_compile_args=cpp_args, ) setup( name='superfastcode2', version='1.0', description='Python package with superfastcode2 C++ extension (PyBind11)', ext_modules=[sfc_module], )
[build-system] requires = ["setuptools", "wheel", "pybind11"] build-backend = "setuptools.build_meta"
Совет Если пакет уже установлен, он появится в списке. Прежде чем продолжить, щелкните значок X, чтобы удалить его.
Совет Если установка завершается неудачно из-за ошибки, связанной с разрешениями, добавьте в конец —user и попробуйте выполнить команду еще раз.
Вызов библиотеки DLL из Python
После того как вы сделаете библиотеки DLL доступными для Python, как описано в предыдущем разделе, можно вызывать функции superfastcode.fast_tanh и superfastcode2.fast_tanh2 из кода Python и сравнивать их эффективность с реализацией Python. Чтобы вызвать библиотеку DLL, выполните следующие действия.
-
Добавьте следующие строки в файл .py, чтобы вызвать методы, экспортированные из библиотек DLL, и отобразить их выходные данные.
from superfastcode import fast_tanh test(lambda d: [fast_tanh(x) for x in d], '[fast_tanh(x) for x in d] (CPython C++ extension)') from superfastcode2 import fast_tanh2 test(lambda d: [fast_tanh2(x) for x in d], '[fast_tanh2(x) for x in d] (PyBind11 C++ extension)')
Примечание. Если команда Запуск без отладки отключена, в Обозревателе решений щелкните правой кнопкой мыши проект Python и выберите команду Назначить запускаемым проектом.
Убедитесь, что подпрограммы C++ выполняются примерно в 5–20 раз быстрее, чем реализация на Python. Обычно выводится следующий результат.
Running benchmarks with COUNT = 500000 [tanh(x) for x in d] (Python implementation) took 0.758 seconds [fast_tanh(x) for x in d] (CPython C++ extension) took 0.076 seconds [fast_tanh2(x) for x in d] (PyBind11 C++ extension) took 0.204 seconds
В выходных данных вы можете увидеть, что расширение PyBind11 не такое быстрое, как расширение CPython, хотя оно все равно должно работать быстрее, чем прямая реализация на Python. Это различие в основном связано с тем, что мы использовали вызов METH_O , который не поддерживает несколько параметров, имен параметров или аргументов ключевых слов. PyBind11 формирует несколько более сложный код, чтобы предоставить вызывающим субъектам интерфейс, более похожий на Python. Но так как тестовый код вызывает функцию 500 000 раз, в результате эти дополнительные временные затраты могут сильно возрасти!
Чтобы сократить временные затраты, можно переместить цикл for в машинный код. Этот подход предполагает использование протокола итератора (или типа py::iterable из PyBind11 в качестве параметра функции) для обработки каждого элемента. Удаление повторяющихся переходов между Python и C++ является эффективным способом сокращения времени, затрачиваемого на обработку последовательности.
Устранение ошибок импорта
Если при попытке импорта модуля вы получаете сообщение ImportError , для разрешения этой проблемы можно использовать один из следующих способов.
- При сборке с помощью ссылки на проект убедитесь, что свойства проекта C++ соответствуют среде Python, активированной для проекта Python, особенно каталоги Include и Library.
- Убедитесь, что ваш выходной файл имеет имя superfastcode.pyd. Файл с любым другим именем или расширением не будет импортирован.
- Если вы установили модуль с помощью файла setup.py, убедитесь, что вы выполнили команду pip в среде Python, активированной для вашего проекта Python. При развертывании среды Python в обозревателе решений должна отображаться запись для superfastcode.
Отладка кода C++
Visual Studio поддерживает совместную отладку кода на Python и C++. В этом разделе вы пошагово выполните процесс с использованием проекта superfastcode. Этот процесс такой же, как для проекта superfastcode2.
-
В Обозревателе решений щелкните проект Python правой кнопкой мыши, выберите Свойства, откройте вкладку Отладка и выберите Отладка>Разрешить отладку машинного кода.
Совет При включении отладки машинного кода окно вывода Python может немедленно закрываться сразу после завершения программы без обычной паузы с сообщением Для продолжения нажмите любую клавишу. Решение: чтобы после включения отладки машинного кода принудительно приостановить выполнение программы, добавьте параметр -i в поле Запуск>Аргументы интерпретатора на вкладке Отладка. Этот аргумент переводит интерпретатор Python в интерактивный режим после выполнения кода, и для закрытия окна интерпретатора необходимо будет нажать клавиши CTRL+Z, а затем ВВОД. Кроме того, если вы не против изменения кода Python, можно добавить в конец программы операторы import os и os.system(«pause») . Этот код дублирует исходный запрос с приостановкой.


Альтернативные подходы
Существуют различные способы для создания расширений Python, приведенные в таблице ниже. Способы CPython и PyBind11 , указанные в первых двух строках, рассматриваются в этой статье.
| Подход | Vintage | Представители |
|---|---|---|
| Модули расширений C/C++ для CPython | 1991 | Стандартная библиотека |
| PyBind11 (рекомендуется для C++) | 2015 | |
| Cython (рекомендуется для C) | 2007 | gevent, kivy |
| HPy | 2019 | |
| mypyc | 2017 | |
| ctypes | 2003 | oscrypto |
| cffi | 2013 | cryptography, pypy |
| SWIG | 1996 | crfsuite |
| Boost.Python | 2002 | |
| cppyy | 2017 |
См. также
Полный пример из этого руководства см. на GitHub по ссылке python-samples-vs-cpp-extension.
Вызов функций из C/C++ в Python
Основная проблема, с которой сталкиваются разработчики, заключается в том, что они хотят использовать библиотеки на C или C++ в своем коде на Python. Это может быть связано с тем, что эти библиотеки были написаны в прошлом и содержат важные функции, которые разработчик хочет использовать, не переписывая их на Python, или они могут быть более эффективными по производительности, чем аналогичные библиотеки на Python.
Возможно, у вас есть библиотека на C++:
// mylib.cpp #include <iostream> extern "C" < void hello() < std::cout << "Hello, World!" << std::endl; >>
И вы хотите вызвать функцию hello() из этой библиотеки в вашем коде на Python. Как это можно сделать?
1. Использование ctypes
Один из способов — использовать модуль ctypes , который является частью стандартной библиотеки Python. ctypes предоставляет возможность создавать и манипулировать C-совместимыми типами данных в Python, и также вызывать функции в динамических библиотеках/разделяемых библиотеках.
Вот как можно использовать ctypes для вызова функции hello() :
from ctypes import cdll # Загрузка библиотеки mylib = cdll.LoadLibrary('./mylib.so') # Вызов функции mylib.hello()
Обратите внимание, что вам потребуется скомпилировать ваш код C++ в разделяемую библиотеку ( mylib.so в Unix-системах или mylib.dll в Windows) перед тем, как вы сможете загрузить его с помощью ctypes .
2. Использование SWIG
SWIG (Simplified Wrapper and Interface Generator) — это другой инструмент, который позволяет вызывать C/C++ код из Python. SWIG генерирует обертки для вызова функций C/C++ из Python.
Вот как можно использовать SWIG:
- Напишите интерфейсный файл для SWIG:
// mylib.i %module mylib % < extern void hello(); %>extern void hello();
- Затем вы можете сгенерировать обертку с помощью SWIG:
swig -python mylib.i
- Это создаст два файла: mylib_wrap.c и mylib.py . Вы можете скомпилировать mylib_wrap.c в разделяемую библиотеку, а затем использовать mylib.py в вашем коде на Python:
import mylib mylib.hello()
Это простые способы вызова C/C++ кода из Python, но они могут быть недостаточно гибкими для сложных случаев использования. Для более продвинутых сценариев могут потребоваться другие инструменты, такие как Cython или Boost.Python.
4. Сборка C и C++ расширений¶
Расширение C для CPython — это общая библиотека (например, файл .so в Linux, .pyd в Windows), которая экспортируется функцией инициализации.
Для импорта общая библиотека должна быть доступна в PYTHONPATH и должна быть именоваться по имени модуля с соответствующим расширением. При использовании distutils автоматически генерируется правильное имя файла.
Функция инициализации имеет сигнатуру:
Она возвращает либо полностью инициализированный модуль, либо PyModuleDef сущность. Дополнительные сведения см. в разделе Инициализация C модулей .
Для модулей с именами только ASCII функция должна иметь имя PyInit_ , а заменяться именем модуля. При использовании Многофазная инициализация допускается использование имен модулей, отличных от ASCII. В этом случае имя функции инициализации равно PyInitU_ , при этом кодируются с использованием Python punycode кодировки, где дефис заменяется на подчеркивание. В 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 в Distributing Python Modules (Legacy version) , чтобы узнать больше о функциях distutils; в этом разделе описываются только модули расширения здания.
Обычно предварительно вычисляют аргументы для 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 ; для получения более подробной информации см. Specifying the files to distribute .
Если исходный дистрибутив был успешно построен, сопровождающие также могут создавать двоичные дистрибутивы. В зависимости от платформы для этого можно использовать одну из следующих команд:
python setup.py bdist_wininst python setup.py bdist_rpm python setup.py bdist_dumb
