- PVSM.RU - https://www.pvsm.ru -

Встраивание PyPy кода в приложения на C

Встраивание PyPy кода в приложения на C - 1
На конференции PyGrunn 2016 [1] я выступил с докладом о пакете Python cffi и его использовании для встраивания PyPy кода в приложения на C.

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

Встраиваемый API

Первый шаг заключается в определении интерфейса, который определяет, как приложению на С следует вызывать наш Python код. Мы должны указать это с помощью прототипов C-функций. Для нашего примера мы рассмотрим функцию, которая выполняет какие-то вычисления, но, конечно, это может быть все что угодно.

float compute(float first, float second);

Теперь мы должны реализовать эти вычисления на Python:

from my_library import ffi, lib

@ffi.def_extern()
def compute(first, second):
    """ Вычисляет абсолютное расстояние между двумя числами. """
    return abs(first - second)

Этот фрагмент содержит несколько особенных вещей для его правильного встраивания. Первая строка импортирует объекты ffi и lib из динамической библиотеки. Делая это реализация получает доступ к функциям, предоставляемым cffi и их можно использовать для более сложных задач, таких как выделение памяти. Имя my_library определено ниже и соответствует имени нашей динамической библиотеки.

Второе, что мы замечаем в этом фрагменте — это декоратор @ffi.def_extern. Он говорит cffi, что декорированные функции должны быть представлены в публичном API, создаваемой C-библиотеки. Декорированные функции будут сопоставлены с прототипами, указанными в объявлении API и их аргументами и возвращаемые значения будут преобразовываться автоматически.

Скрипт генерирующий библиотеку

Теперь, когда у нас есть API и его реализация, мы должны на самом деле куда-то его встроить. Для этого мы используем скрипт, который генерирует динамическую библиотеку. Он требует, чтобы два фрагмента кода, приведенные выше, находились в файлах api.h и implementation.py.

import cffi
ffi = cffi.FFI()

ffi.embedding_api(open("api.h").read())
ffi.embedding_init_code(open("implementation.py").read())

ffi.set_source("my_library", "")
ffi.compile(verbose=True)

Этот скрипт очень прост. Мы должны указать наш API и предоставить его реализацию. Они оба читаются с диска и соответствуют фрагментам кода, приведенным в предыдущем разделе.

После указания исходников, мы должны сказать cffi название нашей библиотеки. В этом примере это my_library. Кроме того, здесь есть место для добавления дополнительного C-кода, предоставляющего типы для заголовочного файла нашего API, например, с помощью подключения соответствующих заголовочных файлов (что не допускается в embedding_api). Остается только скомпилировать исходники, чтобы создать файл нашей библиотеки.

Запуск скрипта выводит некоторую информацию и создает нашу библиотеку:

$ pypy embed.py
generating ./my_library.c
running build_ext
building 'my_library' extension
...

$ ls my_library.dylib
-rwxr-xr-x  1 djinn  staff  9856 May 15 14:46 my_library.dylib

Все что осталось — это где-нибудь ее использовать!

Использующее приложение

Использовать встраиваемый Python-код на самом деле очень просто. Это можно сделать с помощью следующего кода:

#include <stdio.h>
#include "api.h"

int main(void) {
    float result = compute(12.34f, 10.0f);
    printf("The result: %fn", result);

    return 0;
}

Как вы видите, для вызова нашего Python-кода практически ничего не нужно. Используя API CPython, вы должны были бы запустить интерпретатор и выполнить множество преобразований параметров и возвращаемого значения. Но не с cffi! Созданная библиотека берет все на себя, так что вы можете сосредоточиться на действительно полезной работе. Последнее, что я должен показать вам, это как скомпилировать и запустить этот код.

$ clang -o test test.c my_library.dylib

$ ./test
The result: 2.340000

И вот оно! С помощью всего нескольких строк кода мы написали программу на C, которая запускает интерпретатор PyPy и выполняет наш Python-код, как если бы это был код на C. Конечно, я показал вам только основы, но это действительно мощная технология. Для получения дополнительной информации, можно посмотреть в документацию cffi [2].

Автор: DuDDiTs

Источник [3]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/python/127725

Ссылки в тексте:

[1] PyGrunn 2016: http://www.pygrunn.org/

[2] документацию cffi: http://cffi.readthedocs.io/en/latest/embedding.html

[3] Источник: https://habrahabr.ru/post/302050/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best