Загрузка С библиотек
Python может загружать библиотеки на С и вызывать функции из них. Для этого можно воспользоваться модулем стандартной библиотеки ctypes
или модулем cffi
pip.
Модуль ctypes
требует явного описания сигнатуры (списка аргументов и возвращаемого значения) вызываемой функции на Python, cffi
, же включает синтаксический анализатор C, благодаря которому может разбирать заголовочные файлы .h
и получать оттуда информацию о структурах.
Загрузка библиотеки в ctypes
import ctypes
# В *nix разделяемые библиотеки - файлы .so
lib = ctypes.CDLL('./mylib.so')
# В Windows - файлы .dll
lib = ctypes.CDLL('./mylib.dll')
Вызов функции в ctypes
foo = lib.foo
foo.restype = ctypes.c_double
foo.argtypes = [ctypes.c_int, ctypes.c_double]
# Теперь функцию foo можно вызывать, как обычную функцию Python.
ret = foo(5, 3.2)
print(ret)
Некоторые популярные типы ctypes
Тип ctypes | Тип C | Тип Python |
---|---|---|
c_byte | char | int |
c_ubyte | unsigned char | int |
c_int | int | int |
c_double | double | float |
c_char_p | char * | str или None |
c_int * 10 | int [10] | list(int, …) |
Так как строки в Python являются константами, для создания изменяемого массива типа c_char_p
используется метод create_string_buffer
. Подробнее в документации.
Загрузка библиотеки и вызов функции в cffi
import cffi
# Создаем объект пространства имен cffi
ffi = cffi.FFI()
# Загружаем заголовочный файл
with open("mylib_header.h") as f:
ffi.cdef(f.read())
# Загружаем библиотеку
lib = ffi.dlopen("mylib.so")
# Вызываем функцию
result = lib.foo(5, 3.2)
# Создаем объект - структуру данных объявленную в заголовочном файле
my_data_struct = self.ffi.new("DataStruct *")
my_data_struct.a = 15 # Работаем с полями структуры на Python
ffi.buffer(my_data_struct) # Получаем bytes представление структуры
Что еще нужно знать о вызове С функций
- Написание критичных с точки зрения производительности участков кода на C — один из стандартных способов разогнать Python.
- Ошибка в С библиотеке не может быть обработана на уровне Python и приведет к аварийному завершению интерпретатора.
- Анализатор С
pycparser
который используетcffi
поддерживает не все возможности языка С, а также не умеет обрабатывать директивы препроцессора (#include
,#ifdef
и т.п.). - Для CPython можно писать модули С — CPython Extensions.
binlib.txt · Последнее изменение: 2023/04/10 09:50 — root
Если не указано иное, содержимое этой вики предоставляется на условиях следующей лицензии: CC Attribution-Share Alike 4.0 International