====== Загрузка С библиотек ====== 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''. Подробнее в [[https://docs.python.org/3.6/library/ctypes.html|документации]].
===== Загрузка библиотеки и вызов функции в 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 можно писать модули С — [[http://book.pythontips.com/en/latest/python_c_extension.html|CPython Extensions]].