К сторонним функциям, можно обращаться как к атрибутам загруженных C библиотек. Объекты C-функций, созданные таким образом, по умолчанию принимают любое количество аргументов, принимают любые экземпляры данных модуля ctypes
в качестве аргументов и возвращают тип результата по умолчанию, указанный загрузчиком библиотеки.
Все они являются экземплярами частного класса ctypes._FuncPtr
.
ctypes._FuncPtr
:Класс ctypes._FuncPtr
это базовый класс для всех вызываемых C-функций, загруженных из внешних библиотек языка C.
Экземпляры сторонних C-функций также являются типами данных, совместимыми с языком C. Они представляют собой указатели на C-функции.
Их поведение можно настроить, назначив специальные атрибуты объекта внешней C-функции.
_FuncPtr.restype
:Атрибут _FuncPtr.restype
назначает тип ctypes
, для указания возвращаемого типа внешней C-функции. Используйте None
для void
-функции, которые ничего не возвращают.
Атрибуту можно назначить вызываемый объект Python, который не является типом ctypes
, в этом случае предполагается, что функция возвращает тип C int
, а вызываемый объект будет вызываться с целым числом, позволяя дальнейшую обработку или проверку ошибок.
Использование такого поведения не рекомендуется, Для более гибкой постобработки или проверки ошибок используйте тип данных ctypes
в качестве _FuncPtr.restype
и определите вызываемый атрибут _FuncPtr.errcheck
.
>>> from ctypes import * >>> strchr = libc.strchr >>> strchr(b"abcdef", ord("d")) # 8059983 # c_char_p - это указатель на строку >>> strchr.restype = c_char_p >>> strchr(b"abcdef", ord("d")) # b'def' >>> print(strchr(b"abcdef", ord("x"))) # None
_FuncPtr.argtypes
:Атрибут _FuncPtr.argtypes
назначает кортеж типов ctypes
, для указания типов аргументов, которые принимает C-функция.
Когда вызывается внешняя C-функция, каждый фактический аргумент передается методу класса .from_param()
элементов в кортеже _FuncPtr.argtypes
. Этот метод позволяет адаптировать фактический аргумент к объекту, который принимает внешняя C-функция. Например, элемент ctypes.c_char_p
в кортеже _FuncPtr.argtypes
преобразует строку, переданную в качестве аргумента, в объект байтов, используя правила преобразования ctypes
.
>>> from ctypes import * >>> printf = libc.printf >>> printf.argtypes = [c_char_p, c_char_p, c_int, c_double] >>> printf(b"String '%s', Int %d, Double %f\n", b"Hi", 10, 2.2) # String 'Hi', Int 10, Double 2.200000 # 37
Новое: теперь можно размещать элементы в _FuncPtr.argtypes
, не являются типами ctypes
. При этом каждый элемент должен иметь метод .from_param()
, который возвращает значение, используемое в качестве аргумента (целое число, строка, экземпляр ctypes
). Это позволяет определять адаптеры, которые адаптируют пользовательские объекты как параметры внешней C-функции.
_FuncPtr.errcheck
:Атрибут _FuncPtr.errcheck
предназначен для назначения ему функции Python или другого вызываемого объекта. Эта функция будет вызываться с тремя или более аргументами:
callable(result, func, arguments)
:
result
- это то, что возвращает внешняя C-функция, как указано в атрибуте _FuncPtr.restype
.func
- это сам объект внешней C-функции, он позволяет повторно использовать один и тот же вызываемый объект для проверки или последующей обработки результатов нескольких функций.arguments
- это кортеж, содержащий параметры, первоначально переданные вызову C-функции, что позволяет специализировать поведение на используемых аргументах.>>> def errcheck(result, func, args): ... if not result: ... raise WinError() ... return args ... >>> GetWindowRect.errcheck = errcheck
Объект, который возвращает назначенная функции Python, будет возвращен из вызова C-функции. Также, эта функция Python может проверить значение результата и вызвать исключение, если вызов внешней C-функции завершился неудачно.
ctypes.ArgumentError
:Исключение ctypes.ArgumentError
возникает, когда вызов внешней функции не может преобразовать один из переданных аргументов.
В Windows, когда вызов внешней функции вызывает системное исключение (например, из-за нарушения прав доступа), то оно будет захвачено и заменено подходящим исключением Python. Далее будет вызвано событие аудита ctypes.seh_exception
с аргумента code
, позволяющее перехватчику заменить исключение своим собственным.
Некоторые способы вызова внешних функций могут вызвать событие аудита ctypes.call_function
с аргументами function pointer
и arguments
.