Выбрать главу

C Foreign Function Interface

Пакет CFFI (https://cffi.readthedocs.org/en/latest/) предоставляет простой механизм для взаимодействия с кодом, написанным на C, из Python и PyPy. CFFI рекомендуется использовать с PyPy (http://doc.pypy.org/en/latest/extending.html) для наилучшей совместимости между CPython и PyPy. Он поддерживает два режима: встроенный режим совместимости для бинарных интерфейсов приложения (application binary interface, ABI) (смотрите следующий пример кода) позволяет динамически загружать и запускать функции из исполняемых модулей (по сути, предоставляет такую же функциональность, как LoadLibrary или dlopen), а также режим API, который позволяет выполнять сборку модулей расширения C[103].

Установите его с помощью pip:

$ pip install cffi

Рассмотрим пример взаимодействия ABI:

Строка может быть получена из объявления функции, расположенного в заголовочном файле С.

Открываем общую библиотеку (*.DLL или *.so).

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

ctypes

ctypes (https://docs.python.org/3/library/ctypes.html) — это выбор де-факто для взаимодействия с кодом на C/C++ и CPython; находится в стандартной библиотеке. Предоставляет полный доступ к нативному интерфейсу на С для большей части операционных систем (например, kernel32 для Windows, или libc для *nix), а также поддерживает загрузку и взаимодействие с динамическими библиотеками — разделяемыми объектами (*.so) или DLL — во время выполнения программы. Вместе с ctypes поставляется множество типов для взаимодействия с API системы, что позволяет вам легко определить собственные сложные типы вроде структур и объединений, а также модифицировать элементы вроде внутренних полей и выравнивания, если это нужно. Она может быть несколько неудобна в использовании (поскольку вам нужно вводить много дополнительных символов), но вместе с модулем стандартной библиотеки struct (https://docs.python.org/3.5/library/struct.html) у вас, по сути, будет полный контроль над тем, как ваши типы данных преобразуются в типы, которые могут применять методы, написанные на чистом C/C++.

Например, структура C, определенная следующим образом в файле my_struct.h:

struct my_struct {

····int a;

····int b;

};

может быть реализована так, как показано в файле с именем my_struct.py:

import ctypes

class my_struct(ctypes.Structure):

····_fields_ = [("a", c_int),

················("b", c_int)]

F2PY

Генератор интерфейса Fortran-к-Python (F2PY) (http://docs.scipy.org/doc/numpy/f2py/) является частью NumPy. Чтобы его получить, установите NumPy с помощью команды pip:

$ pip install numpy

Предоставляет гибкую функцию командной строки, f2py, которая может быть использована тремя разными способами (все они задокументированы в руководстве к F2PY по адресу http://docs.scipy.org/doc/numpy/f2py/getting-started.html). Если вы имеете доступ к управлению исходным кодом, то можете добавить особые комментарии с инструкциями для F2PY, которые показывают предназначение каждого аргумента (какие элементы являются входными, а какие — возвращаемыми), а затем запустить F2PY:

$ f2py — c fortran_code.f — m python_module_name

В противном случае F2PY способен сгенерировать промежуточный файл с расширением *.pyf, который вы можете модифицировать, чтобы получить такой же результат. Для этого потребуются три шага:

Автоматически сгенерируйте промежуточный файл, который определяет интерфейс между сигнатурами функций языков FORTRAN и Python.

Отредактируйте файл, чтобы входные и выходные переменные были корректно размечены.

Теперь скомпилируйте код и постройте модули расширения.

SWIG

Упрощенный упаковщик и генератор интерфейсов (Simplified Wrapper Interface Generator, SWIG) (http://www.swig.org/) поддерживает большое количество языков сценария, включая Python. Этот широко распространенный инструмент командной строки генерирует привязки для интерпретируемых языков из аннотированных файлов заголовков C/C++.

вернуться

103

Необходимо особенно тщательно писать расширения на C, чтобы убедиться, что вы регистрируете свои потоки для интерпретатора (http://docs.python.org/c-api/init.html#threads).