Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Industrial programming >> Python

Python — программирование расширений с помощью C

Предыдущая страницаСледующая страница

Любой код, который вы пишете с использованием любого скомпилированного языка, такого как C, C++ или Java, можно интегрировать или импортировать в другой скрипт Python. Этот код считается «расширением».

Модуль расширения Python — это не что иное, как обычная библиотека C. На машинах Unix эти библиотеки обычно заканчиваются на .so. (для общего объекта). На компьютерах с Windows вы обычно видите .dll (для динамически подключаемой библиотеки).

Предварительные условия для написания расширений

Чтобы начать писать расширение, вам понадобятся заголовочные файлы Python.

Кроме того, предполагается, что вы хорошо знаете C или C++ для написания любого расширения Python с использованием программирования C.

Первый взгляд на расширение Python

Для первого взгляда на модуль расширения Python вам нужно сгруппировать свой код на четыре части —

Файл заголовка Python.h

Вам нужно включить Python.h заголовочный файл в вашем исходном файле C, который дает вам доступ к внутреннему API Python, используемому для подключения вашего модуля к интерпретатору.

Не забудьте включить Python.h перед любыми другими заголовками, которые могут вам понадобиться. Вам нужно следовать включениям функций, которые вы хотите вызывать из Python.

Функции C

Сигнатуры реализации ваших функций на C всегда принимают одну из следующих трех форм:

01

Каждое из предыдущих объявлений возвращает объект Python. Не существует такой вещи, как пустота Функция в Python такая же, как и в C. Если вы не хотите, чтобы ваши функции возвращали значение, верните C-эквивалент функции None в Python. ценность. Заголовки Python определяют макрос Py_RETURN_NONE, который делает это за нас.

Имена ваших функций C могут быть любыми, поскольку они никогда не видны за пределами модуля расширения. Они определены как статические функция.

Ваши функции C обычно называются путем объединения имен модуля Python и функций, как показано здесь —

10 

Это функция Python, которая называется func. внутри модуля module . Вы будете помещать указатели на свои функции C в таблицу методов для модуля, который обычно идет следующим в вашем исходном коде.

Таблица сопоставления методов

Эта таблица методов представляет собой простой массив структур PyMethodDef. Эта структура выглядит примерно так —

28

Вот описание членов этой структуры —

  • имя_мл − Это имя функции, которое представляет интерпретатор Python, когда она используется в программах Python.

  • мл_мет − Это должен быть адрес функции, имеющей любую из сигнатур, описанных в предыдущем разделе.

  • ml_flags − Это сообщает интерпретатору, какую из трех сигнатур использует ml_meth.

    • Этот флаг обычно имеет значение METH_VARARGS.

    • Этот флаг можно объединить побитовым ИЛИ с METH_KEYWORDS, если вы хотите разрешить использование аргументов ключевого слова в своей функции.

    • Это также может иметь значение METH_NOARGS, указывающее, что вы не хотите принимать какие-либо аргументы.

  • ml_doc − Это строка документации для функции, которая может быть NULL, если вам не хочется ее писать.

Эта таблица должна быть завершена дозорным элементом, состоящим из значений NULL и 0 для соответствующих членов.

Пример

Для определенной выше функции у нас есть следующая таблица сопоставления методов —

32

Функция инициализации

Последняя часть вашего модуля расширения — это функция инициализации. Эта функция вызывается интерпретатором Python при загрузке модуля. Требуется, чтобы функция называлась initModule. , где Модуль имя модуля.

Функцию инициализации необходимо экспортировать из библиотеки, которую вы будете создавать. Заголовки Python определяют PyMODINIT_FUNC, чтобы включить соответствующие заклинания, чтобы это произошло для конкретной среды, в которой мы компилируем. Все, что вам нужно сделать, это использовать его при определении функции.

Ваша функция инициализации C обычно имеет следующую общую структуру —

40

Вот описание Py_InitModule3. функция —

  • функция − Это функция, которую нужно экспортировать.

  • модуль _методы − Это имя таблицы сопоставления, определенное выше.

  • строка документации − Это комментарий, который вы хотите оставить в своем расширении.

Все это вместе выглядит следующим образом —

58

Пример

Простой пример, в котором используются все вышеперечисленные концепции —

61

Здесь Py_BuildValue функция используется для создания значения Python. Сохраните приведенный выше код в файле hello.c. Мы увидим, как скомпилировать и установить этот модуль для вызова из скрипта Python.

Создание и установка расширений

distutils package позволяет очень легко распространять модули Python, как чистые Python, так и модули расширения, стандартным способом. Модули распространяются в виде исходного кода, создаются и устанавливаются с помощью сценария установки, который обычно называется setup.py. следующим образом.

Для вышеуказанного модуля вам необходимо подготовить следующий скрипт setup.py —

73

Теперь используйте следующую команду, которая выполнит все необходимые шаги компиляции и связывания с правильными командами и флагами компилятора и компоновщика и скопирует полученную динамическую библиотеку в соответствующий каталог —

89

В системах на базе Unix вам, скорее всего, потребуется запустить эту команду от имени пользователя root, чтобы иметь права на запись в каталог site-packages. Обычно это не проблема в Windows.

Импорт расширений

После того, как вы установили расширение, вы сможете импортировать и вызывать это расширение в своем скрипте Python следующим образом —

99

Это даст следующий результат —

107

Передача параметров функции

Поскольку вы, скорее всего, захотите определить функции, которые принимают аргументы, вы можете использовать одну из других сигнатур для ваших функций C. Например, следующая функция, которая принимает некоторое количество параметров, будет определена следующим образом —

114

Таблица методов, содержащая запись для новой функции, будет выглядеть так:

129

Вы можете использовать API PyArg_ParseTuple для извлечения аргументов из одного указателя PyObject, переданного в вашу функцию C.

Первым аргументом PyArg_ParseTuple является аргумент args. Это объект, который вы будете анализировать. . Второй аргумент — это строка формата, описывающая аргументы в том виде, в котором вы ожидаете их появление. Каждый аргумент представлен одним или несколькими символами в строке формата следующим образом.

134

Компиляция новой версии вашего модуля и ее импорт позволяет вам вызывать новую функцию с любым количеством аргументов любого типа —

146

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

PyArg_ParseTuple Функция

Вот стандартная подпись для PyArg_ParseTuple. функция —

159

Эта функция возвращает 0 в случае ошибки и значение, отличное от 0, в случае успеха. tuple — это PyObject*, который был вторым аргументом функции C. Здесь формат это строка C, описывающая обязательные и необязательные аргументы.

Вот список кодов форматов для PyArg_ParseTuple. функция —

<тд> <тд> <тд>
Код Тип C Значение
с знак Строка Python длиной 1 становится символом C.
д двойной Python float становится двойным C.
f плавающий Python float становится float C.
i целое Int Python становится int C.
л длинный Python int становится C long.
Л длинный длинный Python int становится long long в C
О PyObject* Получает ненулевую заимствованную ссылку на аргумент Python.
s char* Строка Python без встроенных нулей в C char*.
s# char*+int Любая строка Python с адресом C и длиной.
t# char*+int Односегментный буфер только для чтения по адресу C и длине.
н Py_UNICODE* Python Unicode без встроенных нулей в C.
u# Py_UNICODE*+int Любой адрес Python Unicode C и длина.
w# char*+int Чтение/запись односегментного буфера по адресу C и длине.
з char* Как и s, также принимает None (устанавливает C char* в NULL).
z# char*+int Как и s#, также принимает None (устанавливает C char* в NULL).
(...) согласно ... Последовательность Python обрабатывается как один аргумент для каждого элемента.
| Следующие аргументы являются необязательными.
: Конец формата, за которым следует имя функции для сообщений об ошибках.
; Конец формата, за которым следует весь текст сообщения об ошибке.

Возвращаемые значения

Py_BuildValue принимает строку формата, очень похожую на PyArg_ParseTuple делает. Вместо передачи адресов значений, которые вы создаете, вы передаете фактические значения. Вот пример, показывающий, как реализовать функцию добавления —

165

Вот как это выглядело бы, если бы было реализовано на Python —

179

Вы можете вернуть два значения из своей функции следующим образом, это будет захвачено с помощью списка в Python.

186

Вот как это выглядело бы, если бы было реализовано на Python —

197

Py_BuildValue Функция

Вот стандартная подпись для Py_BuildValue. функция —

202

Здесь формат это строка C, описывающая объект Python для сборки. Следующие аргументы Py_BuildValue являются значениями C, из которых строится результат. PyObject* результатом является новая ссылка.

В следующей таблице перечислены часто используемые строки кода, ноль или более из которых объединены в строковый формат.

Код Тип C Значение
с знак C char становится строкой Python длиной 1.
д двойной C double становится числом с плавающей запятой Python.
f плавающий Поплавок C становится поплавком Python.
i целое C int становится Python int.
л длинный C long становится Python int.
Н PyObject* Передает объект Python и крадет ссылку.
О PyObject* Передает объект Python и выполняет INCREF как обычно.
О& convert+void* Произвольное преобразование
s char* C 0-terminated char* в строку Python или NULL в None.
s# char*+int C char* и длина в строку Python или NULL в None.
н Py_UNICODE* Строка уровня C, оканчивающаяся нулем, в Python Unicode или от NULL до None.
u# Py_UNICODE*+int Строка уровня C и длина в Python Unicode или NULL в None.
w# char*+int Чтение/запись односегментного буфера по адресу C и длине.
з char* Как и s, также принимает None (устанавливает C char* в NULL).
z# char*+int Как и s#, также принимает None (устанавливает C char* в NULL).
(...) согласно ... Создает кортеж Python из значений C.
[...] согласно ... Создает список Python из значений C.
{...} согласно ... Создает словарь Python из значений C, чередуя ключи и значения.

Код {...} строит словари из четного числа значений C, попеременно ключей и значений. Например, Py_BuildValue("{issi}",23,"zig","zag",42) возвращает словарь, подобный Python {23:'zig','zag':42}.


Python

  1. Объектно-ориентированное программирование Python
  2. Оператор Python Print():как печатать с примерами
  3. Функция Python String strip() с ПРИМЕРОМ
  4. Количество строк Python() с ПРИМЕРАМИ
  5. Python String format() Объясните с ПРИМЕРАМИ
  6. Метод Python String find() с примерами
  7. Лямбда-функции Python с ПРИМЕРАМИ
  8. Функция Python round() с ПРИМЕРАМИ
  9. Функция Python map() с ПРИМЕРАМИ
  10. Python Timeit() с примерами