Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Предыдущая версия справа и слева Предыдущая версия
ext:lib [2023/04/10 09:49]
root удалено
— (текущий)
Строка 1: Строка 1:
-<div slide> 
- 
-====== Загрузка С библиотек ====== 
- 
-Python может загружать библиотеки на С и вызывать функции из них. Для этого можно воспользоваться модулем стандартной библиотеки ''ctypes'' или  модулем ''cffi''<sup>pip</sup>. 
- 
-Модуль ''ctypes'' требует явного описания сигнатуры (списка аргументов и возвращаемого значения) вызываемой функции на Python, ''cffi'', же включает синтаксический анализатор C, благодаря которому может разбирать заголовочные файлы ''.h'' и получать оттуда информацию о структурах. 
- 
-===== Загрузка библиотеки в ctypes ===== 
- 
-<sxh python> 
-import ctypes 
- 
-# В *nix разделяемые библиотеки - файлы .so 
-lib = ctypes.CDLL('./mylib.so') 
- 
-# В Windows - файлы .dll 
-lib = ctypes.CDLL('./mylib.dll') 
-</sxh> 
- 
-</div><div slide> 
- 
-===== Вызов функции в ctypes ===== 
- 
-<sxh python> 
- 
-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) 
-</sxh> 
- 
-</div><div slide> 
- 
-==== Некоторые популярные типы 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|документации]]. 
- 
-</div><div slide> 
- 
-===== Загрузка библиотеки и вызов функции в cffi ===== 
- 
-<sxh python> 
-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 представление структуры 
- 
-</sxh> 
- 
-</div><div slide> 
- 
-===== Что еще нужно знать о вызове С функций ===== 
- 
-  * Написание критичных с точки зрения производительности участков кода на C — один из стандартных способов разогнать Python. 
-  * Ошибка в С библиотеке не может быть обработана на уровне Python и приведет к аварийному завершению интерпретатора. 
-  * Анализатор С ''pycparser'' который использует ''cffi'' поддерживает не все возможности языка С, а также не умеет обрабатывать директивы препроцессора (''#include'', ''#ifdef'' и т.п.). 
-  * Для CPython можно писать модули С — [[http://book.pythontips.com/en/latest/python_c_extension.html|CPython Extensions]]. 
- 
-</div> 
- 
- 
-