Документация Python неофициальный перевод

ctypes.md

2341 строк · 129.3 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.1/library/ctypes.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 15.15. `ctypes` – библиотека для вызова внешних функций из Python89`ctypes` – это библиотека для вызова внешних функций из Python. Она предоставляет совместимые с C типы данных и позволяет вызывать функции из DLL или разделяемых библиотек. Её можно использовать для создания обёрток этих библиотек на чистом Python.1011## 15.15.1. Руководство по ctypes1213Примечание: примеры кода в этом руководстве используют [`doctest`](https://python-all.ru/3.1/library/doctest.html#module-doctest), чтобы убедиться, что они действительно работают. Поскольку некоторые примеры ведут себя по-разному в Linux, Windows или Mac OS X, они содержат директивы doctest в комментариях.1415Примечание: некоторые примеры кода ссылаются на тип ctypes [`c_int`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_int). Этот тип является псевдонимом для типа [`c_long`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_long) в 32-битных системах. Так что не стоит путаться, если выводится [`c_long`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_long), когда вы ожидаете [`c_int`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_int) – на самом деле это один и тот же тип.1617### 15.15.1.1. Загрузка динамически подключаемых библиотек1819`ctypes` предоставляет объекты *cdll*, а в Windows – *windll* и *oledll* для загрузки динамически подключаемых библиотек.2021Библиотеки загружаются через обращение к ним как к атрибутам этих объектов. *cdll* загружает библиотеки, которые экспортируют функции с использованием стандартного соглашения о вызове `cdecl`, тогда как библиотеки *windll* вызывают функции с использованием соглашения о вызове `stdcall`. *oledll* также использует соглашение о вызове `stdcall` и предполагает, что функции возвращают код ошибки Windows `HRESULT`. Этот код ошибки используется для автоматического возбуждения исключения [`WindowsError`](https://python-all.ru/3.1/library/exceptions.html#WindowsError) при сбое вызова функции.2223Вот несколько примеров для Windows. `msvcrt` – это стандартная библиотека C от Microsoft. Она содержит большинство стандартных функций C и использует соглашение о вызовах cdecl.2425```python26>>> from ctypes import *27>>> print(windll.kernel32) # doctest: +WINDOWS28<WinDLL 'kernel32', handle ... at ...>29>>> print(cdll.msvcrt) # doctest: +WINDOWS30<CDLL 'msvcrt', handle ... at ...>31>>> libc = cdll.msvcrt # doctest: +WINDOWS32>>>33```3435Windows автоматически добавляет обычный суффикс файла `.dll`.3637В Linux необходимо указывать имя файла *с расширением* для загрузки библиотеки, поэтому обращение через атрибуты не может использоваться для загрузки библиотек. Следует использовать либо метод `LoadLibrary()` загрузчиков DLL, либо загружать библиотеку, создавая экземпляр CDLL через вызов конструктора:3839```python40>>> cdll.LoadLibrary("libc.so.6") # doctest: +LINUX41<CDLL 'libc.so.6', handle ... at ...>42>>> libc = CDLL("libc.so.6")     # doctest: +LINUX43>>> libc                         # doctest: +LINUX44<CDLL 'libc.so.6', handle ... at ...>45>>>46```4748### 15.15.1.2. Доступ к функциям загруженных DLL4950Функции доступны как атрибуты объектов DLL:5152```python53>>> from ctypes import *54>>> libc.printf55<_FuncPtr object at 0x...>56>>> print(windll.kernel32.GetModuleHandleA) # doctest: +WINDOWS57<_FuncPtr object at 0x...>58>>> print(windll.kernel32.MyOwnFunction) # doctest: +WINDOWS59Traceback (most recent call last):60  File "<stdin>", line 1, in ?61  File "ctypes.py", line 239, in __getattr__62    func = _StdcallFuncPtr(name, self)63AttributeError: function 'MyOwnFunction' not found64>>>65```6667Обратите внимание, что системные DLL win32, такие как `kernel32` и `user32`, часто экспортируют как ANSI-, так и UNICODE-версии функций. Версия UNICODE экспортируется с добавлением `W` к имени, а версия ANSI – с добавлением `A`. Функция win32 `GetModuleHandle`, которая возвращает *дескриптор модуля* для заданного имени модуля, имеет следующий прототип на C, и макрос используется для предоставления одной из них как `GetModuleHandle` в зависимости от того, определён ли UNICODE:6869```python70/* ANSI version */71HMODULE GetModuleHandleA(LPCSTR lpModuleName);72/* UNICODE version */73HMODULE GetModuleHandleW(LPCWSTR lpModuleName);74```7576*windll* не пытается выбрать одну из них магическим образом; необходимо явно указывать нужную версию, обращаясь к `GetModuleHandleA` или `GetModuleHandleW`, и затем вызывать её с объектами bytes или string соответственно.7778Иногда DLL экспортируют функции с именами, которые не являются допустимыми идентификаторами Python, например, `"??2@YAPAXI@Z"`. В этом случае для получения функции приходится использовать [`getattr()`](https://python-all.ru/3.1/library/functions.html#getattr):7980```python81>>> getattr(cdll.msvcrt, "??2@YAPAXI@Z") # doctest: +WINDOWS82<_FuncPtr object at 0x...>83>>>84```8586В Windows некоторые DLL экспортируют функции не по имени, а по порядковому номеру. К таким функциям можно получить доступ, индексируя объект DLL по порядковому номеру:8788```python89>>> cdll.kernel32[1] # doctest: +WINDOWS90<_FuncPtr object at 0x...>91>>> cdll.kernel32[0] # doctest: +WINDOWS92Traceback (most recent call last):93  File "<stdin>", line 1, in ?94  File "ctypes.py", line 310, in __getitem__95    func = _StdcallFuncPtr(name, self)96AttributeError: function ordinal 0 not found97>>>98```99100### 15.15.1.3. Вызов функций101102Эти функции можно вызывать как любые другие вызываемые объекты Python. В этом примере используется функция `time()`, возвращающая системное время в секундах с начала эпохи Unix, и функция `GetModuleHandleA()`, возвращающая дескриптор модуля win32.103104В этом примере обе функции вызываются с нулевым указателем (в качестве нулевого указателя следует использовать `None`):105106```python107>>> print(libc.time(None)) # doctest: +SKIP1081150640792109>>> print(hex(windll.kernel32.GetModuleHandleA(None))) # doctest: +WINDOWS1100x1d000000111>>>112```113114`ctypes` пытается защитить от вызова функций с неверным количеством аргументов или неверным соглашением о вызовах. К сожалению, это работает только в Windows. Для этого анализируется стек после возврата функции, поэтому, хотя и возникает ошибка, функция *была* вызвана:115116```python117>>> windll.kernel32.GetModuleHandleA() # doctest: +WINDOWS118Traceback (most recent call last):119  File "<stdin>", line 1, in ?120ValueError: Procedure probably called with not enough arguments (4 bytes missing)121>>> windll.kernel32.GetModuleHandleA(0, 0) # doctest: +WINDOWS122Traceback (most recent call last):123  File "<stdin>", line 1, in ?124ValueError: Procedure probably called with too many arguments (4 bytes in excess)125>>>126```127128То же исключение возбуждается при вызове функции с соглашением `stdcall` с использованием соглашения о вызове `cdecl`, или наоборот:129130```python131>>> cdll.kernel32.GetModuleHandleA(None) # doctest: +WINDOWS132Traceback (most recent call last):133  File "<stdin>", line 1, in ?134ValueError: Procedure probably called with not enough arguments (4 bytes missing)135>>>136137>>> windll.msvcrt.printf(b"spam") # doctest: +WINDOWS138Traceback (most recent call last):139  File "<stdin>", line 1, in ?140ValueError: Procedure probably called with too many arguments (4 bytes in excess)141>>>142```143144Чтобы узнать правильное соглашение о вызовах, необходимо заглянуть в C-заголовочный файл или документацию вызываемой функции.145146В Windows `ctypes` использует структурированную обработку исключений Win32 для предотвращения сбоев из-за ошибок защиты общего доступа при вызове функций с недопустимыми значениями аргументов:147148```python149>>> windll.kernel32.GetModuleHandleA(32) # doctest: +WINDOWS150Traceback (most recent call last):151  File "<stdin>", line 1, in ?152WindowsError: exception: access violation reading 0x00000020153>>>154```155156Однако есть достаточно способов привести к краху Python с помощью `ctypes`, поэтому в любом случае следует соблюдать осторожность.157158`None`, целые числа, объекты bytes и (юникодные) строки – единственные нативные объекты Python, которые можно напрямую использовать в качестве параметров при вызовах этих функций. `None` передаётся как указатель C `NULL`, объекты bytes и строки передаются как указатель на блок памяти, содержащий их данные (`char *` или `wchar_t *`). Целые числа Python передаются как тип C `int`, используемый по умолчанию на данной платформе, их значение маскируется, чтобы поместиться в тип C.159160Прежде чем перейти к вызову функций с другими типами параметров, необходимо узнать больше о типах данных `ctypes`.161162### 15.15.1.4. Базовые типы данных163164`ctypes` определяет ряд примитивных типов данных, совместимых с C:165166| Тип ctypes | Тип C | Тип Python |167| --- | --- | --- |168| [`c_bool`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_bool) | `_Bool` | bool (1) |169| [`c_char`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_char) | `char` | односимвольный объект bytes |170| [`c_wchar`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_wchar) | `wchar_t` | односимвольная строка |171| [`c_byte`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_byte) | `char` | int |172| [`c_ubyte`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_ubyte) | `unsigned char` | int |173| [`c_short`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_short) | `short` | int |174| [`c_ushort`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_ushort) | `unsigned short` | int |175| [`c_int`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_int) | `int` | int |176| [`c_uint`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_uint) | `unsigned int` | int |177| [`c_long`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_long) | `long` | int |178| [`c_ulong`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_ulong) | `unsigned long` | int |179| [`c_longlong`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_longlong) | `__int64` или `long long` | int |180| [`c_ulonglong`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_ulonglong) | `unsigned __int64` или `unsigned long long` | int |181| [`c_float`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_float) | `float` | float |182| [`c_double`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_double) | `double` | float |183| [`c_longdouble`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_longdouble) | `long double` | float |184| [`c_char_p`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_char_p) | `char *` (с завершающим NUL) | объект bytes или `None` |185| [`c_wchar_p`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_wchar_p) | `wchar_t *` (с завершающим NUL) | строка или `None` |186| [`c_void_p`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_void_p) | `void *` | int или `None` |1871881. Конструктор принимает любой объект с истинностным значением.189190Все эти типы можно создать, вызвав их с необязательным инициализатором правильного типа и значения:191192```python193>>> c_int()194c_long(0)195>>> c_wchar_p("Hello, World")196c_wchar_p('Hello, World')197>>> c_ushort(-3)198c_ushort(65533)199>>>200```201202Поскольку эти типы изменяемы, их значение можно изменить и впоследствии:203204```python205>>> i = c_int(42)206>>> print(i)207c_long(42)208>>> print(i.value)20942210>>> i.value = -99211>>> print(i.value)212-99213>>>214```215216Присваивание нового значения экземплярам типов-указателей [`c_char_p`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_char_p), [`c_wchar_p`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_wchar_p) и [`c_void_p`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_void_p) изменяет *адрес памяти*, на который они указывают, *а не содержимое* блока памяти (конечно, нет, потому что объекты bytes в Python неизменяемы):217218```python219>>> s = "Hello, World"220>>> c_s = c_wchar_p(s)221>>> print(c_s)222c_wchar_p('Hello, World')223>>> c_s.value = "Hi, there"224>>> print(c_s)225c_wchar_p('Hi, there')226>>> print(s)                 # первый объект не изменился227Hello, World228>>>229```230231Однако следует быть осторожным и не передавать их функциям, ожидающим указатели на изменяемую память. Если нужны изменяемые блоки памяти, в ctypes есть функция [`create_string_buffer()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.create_string_buffer), которая создаёт их разными способами. Получить доступ к текущему содержимому блока памяти (или изменить его) можно через свойство `raw` ; если требуется обращаться к нему как к строке с завершающим NUL, используйте свойство `value` :232233```python234>>> from ctypes import *235>>> p = create_string_buffer(3)            # создать буфер размером 3 байта, инициализированный нулевыми байтами236>>> print(sizeof(p), repr(p.raw))2373 b'\x00\x00\x00'238>>> p = create_string_buffer(b"Hello")     # создать буфер, содержащий строку, завершающуюся нулевым байтом239>>> print(sizeof(p), repr(p.raw))2406 b'Hello\x00'241>>> print(repr(p.value))242b'Hello'243>>> p = create_string_buffer(b"Hello", 10) # создать буфер на 10 байт244>>> print(sizeof(p), repr(p.raw))24510 b'Hello\x00\x00\x00\x00\x00'246>>> p.value = b"Hi"247>>> print(sizeof(p), repr(p.raw))24810 b'Hi\x00lo\x00\x00\x00\x00\x00'249>>>250```251252Функция [`create_string_buffer()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.create_string_buffer) заменила функцию `c_buffer()` (которая всё ещё доступна как псевдоним), а также функцию `c_string()` из более ранних выпусков ctypes. Чтобы создать изменяемый блок памяти, содержащий символы Unicode типа C `wchar_t`, используйте функцию [`create_unicode_buffer()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.create_unicode_buffer).253254### 15.15.1.5. Вызов функций, продолжение255256Обратите внимание, что printf выводит в реальный канал стандартного вывода, *а не* в [`sys.stdout`](https://python-all.ru/3.1/library/sys.html#sys.stdout), поэтому эти примеры будут работать только в командной строке, а не из *IDLE* или *PythonWin*:257258```python259>>> printf = libc.printf260>>> printf(b"Hello, %s\n", b"World!")261Hello, World!26214263>>> printf(b"Hello, %S\n", "World!")264Hello, World!26514266>>> printf(b"%d bottles of beer\n", 42)26742 bottles of beer26819269>>> printf(b"%f bottles of beer\n", 42.5)270Traceback (most recent call last):271  File "<stdin>", line 1, in ?272ArgumentError: argument 2: exceptions.TypeError: Don't know how to convert parameter 2273>>>274```275276Как упоминалось ранее, все типы Python, кроме целых чисел, строк и объектов bytes, должны быть обёрнуты в соответствующий тип `ctypes`, чтобы их можно было преобразовать в требуемый тип данных C:277278```python279>>> printf(b"An int %d, a double %f\n", 1234, c_double(3.14))280An int 1234, a double 3.14000028131282>>>283```284285### 15.15.1.6. Вызов функций с собственными пользовательскими типами данных286287Вы также можете настроить преобразование аргументов `ctypes`, чтобы экземпляры собственных классов можно было использовать в качестве аргументов функций. `ctypes` ищет атрибут `_as_parameter_` и использует его как аргумент функции. Разумеется, это должно быть целое число, строка или bytes:288289```python290>>> class Bottles:291...     def __init__(self, number):292...         self._as_parameter_ = number293...294>>> bottles = Bottles(42)295>>> printf(b"%d bottles of beer\n", bottles)29642 bottles of beer29719298>>>299```300301Если вы не хотите хранить данные экземпляра в переменной экземпляра `_as_parameter_`, можно определить [`свойство`](https://python-all.ru/3.1/library/functions.html#property), которое делает этот атрибут доступным по запросу.302303### 15.15.1.7. Задание требуемых типов аргументов (прототипы функций)304305Можно указать требуемые типы аргументов функций, экспортируемых из DLL, с помощью установки атрибута `argtypes`.306307`argtypes` должен быть последовательностью типов C (функция `printf`, вероятно, не самый удачный пример, потому что она принимает переменное количество параметров разных типов в зависимости от строки формата, но с другой стороны это довольно удобно для экспериментов с этой возможностью):308309```python310>>> printf.argtypes = [c_char_p, c_char_p, c_int, c_double]311>>> printf(b"String '%s', Int %d, Double %f\n", b"Hi", 10, 2.2)312String 'Hi', Int 10, Double 2.20000031337314>>>315```316317Указание формата защищает от несовместимых типов аргументов (как прототип для функции C) и пытается преобразовать аргументы в допустимые типы:318319```python320>>> printf(b"%d %d %d", 1, 2, 3)321Traceback (most recent call last):322  File "<stdin>", line 1, in ?323ArgumentError: argument 2: exceptions.TypeError: wrong type324>>> printf(b"%s %d %f\n", b"X", 2, 3)325X 2 3.00000032613327>>>328```329330Если вы определили собственные классы, которые передаёте в вызовы функций, необходимо реализовать метод класса `from_param()`, чтобы их можно было использовать в последовательности `argtypes`. Метод класса `from_param()` получает объект Python, переданный в вызов функции; он должен выполнить проверку типа или всё необходимое, чтобы убедиться, что объект допустим, а затем вернуть сам объект, его атрибут `_as_parameter_` или то, что вы хотите передать в качестве аргумента C-функции в данном случае. Опять же, результатом должно быть целое число, строка, bytes, экземпляр `ctypes` или объект с атрибутом `_as_parameter_`.331332### 15.15.1.8. Типы возвращаемых значений333334По умолчанию считается, что функции возвращают тип C `int`. Другие типы возвращаемых значений можно указать, задав атрибут `restype` объекта функции.335336Вот более сложный пример: в нём используется функция `strchr`, которая ожидает указатель на строку и символ (char) и возвращает указатель на строку:337338```python339>>> strchr = libc.strchr340>>> strchr(b"abcdef", ord("d")) # doctest: +SKIP3418059983342>>> strchr.restype = c_char_p   # c_char_p – указатель на строку343>>> strchr(b"abcdef", ord("d"))344b'def'345>>> print(strchr(b"abcdef", ord("x")))346None347>>>348```349350Если вы хотите избежать вызовов `ord("x")` выше, можно установить атрибут `argtypes`, и второй аргумент будет преобразован из объекта Python bytes, содержащего один символ, в C char:351352```python353>>> strchr.restype = c_char_p354>>> strchr.argtypes = [c_char_p, c_char]355>>> strchr(b"abcdef", b"d")356'def'357>>> strchr(b"abcdef", b"def")358Traceback (most recent call last):359  File "<stdin>", line 1, in ?360ArgumentError: argument 2: exceptions.TypeError: one character string expected361>>> print(strchr(b"abcdef", b"x"))362None363>>> strchr(b"abcdef", b"d")364'def'365>>>366```367368Также можно использовать вызываемый объект Python (например, функцию или класс) в качестве атрибута `restype`, если внешняя функция возвращает целое число. Вызываемый объект будет вызван с *целым числом*, которое возвращает C-функция, и результат этого вызова будет использоваться как результат вызова вашей функции. Это полезно для проверки возвращаемых значений ошибок и автоматического возбуждения исключения:369370```python371>>> GetModuleHandle = windll.kernel32.GetModuleHandleA # doctest: +WINDOWS372>>> def ValidHandle(value):373...     if value == 0:374...         raise WinError()375...     return value376...377>>>378>>> GetModuleHandle.restype = ValidHandle # doctest: +WINDOWS379>>> GetModuleHandle(None) # doctest: +WINDOWS380486539264381>>> GetModuleHandle("something silly") # doctest: +WINDOWS382Traceback (most recent call last):383  File "<stdin>", line 1, in ?384  File "<stdin>", line 3, in ValidHandle385WindowsError: [Errno 126] The specified module could not be found.386>>>387```388389`WinError` – это функция, которая вызывает Windows API `FormatMessage()` для получения строкового представления кода ошибки и *возвращает* исключение. `WinError` принимает необязательный параметр – код ошибки; если он не передан, функция вызывает [`GetLastError()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.GetLastError) для его получения.390391Обратите внимание, что гораздо более мощный механизм проверки ошибок доступен через атрибут `errcheck`; подробности см. в справочном руководстве.392393### 15.15.1.9. Передача указателей (или: передача параметров по ссылке)394395Иногда функция C API ожидает в качестве параметра *указатель* на тип данных, обычно для записи в соответствующее место или если данные слишком велики для передачи по значению. Это также называется *передачей параметров по ссылке*.396397`ctypes` экспортирует функцию [`byref()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.byref), которая используется для передачи параметров по ссылке. Того же эффекта можно достичь с помощью функции [`pointer()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.pointer), хотя [`pointer()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.pointer) делает гораздо больше работы, так как создаёт настоящий объект указателя, поэтому быстрее использовать [`byref()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.byref), если вам не нужен объект указателя в самом Python:398399```python400>>> i = c_int()401>>> f = c_float()402>>> s = create_string_buffer(b'\000' * 32)403>>> print(i.value, f.value, repr(s.value))4040 0.0 b''405>>> libc.sscanf(b"1 3.14 Hello", b"%d %f %s",406...             byref(i), byref(f), s)4073408>>> print(i.value, f.value, repr(s.value))4091 3.1400001049 b'Hello'410>>>411```412413### 15.15.1.10. Структуры и объединения414415Структуры и объединения должны быть производными от базовых классов [`Structure`](https://python-all.ru/3.1/library/ctypes.html#ctypes.Structure) и [`Union`](https://python-all.ru/3.1/library/ctypes.html#ctypes.Union), которые определены в модуле `ctypes`. Каждый подкласс должен определить атрибут `_fields_`. `_fields_` должен быть списком из *2-кортежей*, содержащих *имя поля* и *тип поля*.416417Тип поля должен быть типом `ctypes`, например [`c_int`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_int), или любым другим производным типом `ctypes`: структура, объединение, массив, указатель.418419Вот простой пример структуры POINT, которая содержит два целых числа с именами *x* и *y*, а также показывает, как инициализировать структуру в конструкторе:420421```python422>>> from ctypes import *423>>> class POINT(Structure):424...     _fields_ = [("x", c_int),425...                 ("y", c_int)]426...427>>> point = POINT(10, 20)428>>> print(point.x, point.y)42910 20430>>> point = POINT(y=5)431>>> print(point.x, point.y)4320 5433>>> POINT(1, 2, 3)434Traceback (most recent call last):435  File "<stdin>", line 1, in ?436ValueError: too many initializers437>>>438```439440Однако можно создавать гораздо более сложные структуры. Структуры могут сами содержать другие структуры, используя структуру в качестве типа поля.441442Вот структура RECT, которая содержит две точки с именами *upperleft* и *lowerright*:443444```python445>>> class RECT(Structure):446...     _fields_ = [("upperleft", POINT),447...                 ("lowerright", POINT)]448...449>>> rc = RECT(point)450>>> print(rc.upperleft.x, rc.upperleft.y)4510 5452>>> print(rc.lowerright.x, rc.lowerright.y)4530 0454>>>455```456457Вложенные структуры также можно инициализировать в конструкторе несколькими способами:458459```python460>>> r = RECT(POINT(1, 2), POINT(3, 4))461>>> r = RECT((1, 2), (3, 4))462```463464полей [*descriptor*](https://python-all.ru/3.1/glossary.html#term-descriptor) можно получить из *класса*; они полезны для отладки, так как предоставляют полезную информацию:465466```python467>>> print(POINT.x)468<Field type=c_long, ofs=0, size=4>469>>> print(POINT.y)470<Field type=c_long, ofs=4, size=4>471>>>472```473474### 15.15.1.11. Выравнивание структур/объединений и порядок байтов475476По умолчанию поля Structure и Union выравниваются так же, как это делает компилятор C. Можно переопределить это поведение, указав атрибут класса `_pack_` в определении подкласса. Он должен быть установлен в положительное целое число и задает максимальное выравнивание для полей. Это то же самое, что делает `#pragma pack(n)` в MSVC.477478`ctypes` использует собственный порядок байтов для структур и объединений. Для создания структур с нестандартным порядком байтов можно использовать один из базовых классов [`BigEndianStructure`](https://python-all.ru/3.1/library/ctypes.html#ctypes.BigEndianStructure), [`LittleEndianStructure`](https://python-all.ru/3.1/library/ctypes.html#ctypes.LittleEndianStructure), `BigEndianUnion` и `LittleEndianUnion`. Эти классы не могут содержать поля-указатели.479480### 15.15.1.12. Битовые поля в структурах и объединениях481482Можно создавать структуры и объединения, содержащие битовые поля. Битовые поля возможны только для целочисленных полей; ширина битового поля задается третьим элементом в кортежах `_fields_`:483484```python485>>> class Int(Structure):486...     _fields_ = [("first_16", c_int, 16),487...                 ("second_16", c_int, 16)]488...489>>> print(Int.first_16)490<Field type=c_long, ofs=0:0, bits=16>491>>> print(Int.second_16)492<Field type=c_long, ofs=0:16, bits=16>493>>>494```495496### 15.15.1.13. Массивы497498Массивы – это последовательности, содержащие фиксированное количество экземпляров одного типа.499500Рекомендуемый способ создания типов массивов – умножение типа данных на положительное целое число:501502```python503TenPointsArrayType = POINT * 10504```505506Вот пример несколько искусственного типа данных – структуры, содержащей 4 точки POINT среди прочего:507508```python509>>> from ctypes import *510>>> class POINT(Structure):511...    _fields_ = ("x", c_int), ("y", c_int)512...513>>> class MyStruct(Structure):514...    _fields_ = [("a", c_int),515...                ("b", c_float),516...                ("point_array", POINT * 4)]517>>>518>>> print(len(MyStruct().point_array))5194520>>>521```522523Экземпляры создаются обычным способом – вызовом класса:524525```python526arr = TenPointsArrayType()527for pt in arr:528    print(pt.x, pt.y)529```530531Приведенный выше код выводит серию строк `0 0`, потому что содержимое массива инициализируется нулями.532533Можно также указать инициализаторы правильного типа:534535```python536>>> from ctypes import *537>>> TenIntegers = c_int * 10538>>> ii = TenIntegers(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)539>>> print(ii)540<c_long_Array_10 object at 0x...>541>>> for i in ii: print(i, end=" ")542...5431 2 3 4 5 6 7 8 9 10544>>>545```546547### 15.15.1.14. Указатели548549Экземпляры указателей создаются вызовом функции [`pointer()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.pointer) на типе `ctypes`:550551```python552>>> from ctypes import *553>>> i = c_int(42)554>>> pi = pointer(i)555>>>556```557558Экземпляры указателей имеют атрибут `contents`, который возвращает объект, на который указывает указатель – объект `i` из примера выше:559560```python561>>> pi.contents562c_long(42)563>>>564```565566Обратите внимание, что `ctypes` не поддерживает OOR (возврат исходного объекта), он создаёт новый эквивалентный объект каждый раз при получении атрибута:567568```python569>>> pi.contents is i570False571>>> pi.contents is pi.contents572False573>>>574```575576Присвоение другого экземпляра [`c_int`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_int) атрибуту contents указателя приведет к тому, что указатель будет указывать на область памяти, где этот экземпляр хранится:577578```python579>>> i = c_int(99)580>>> pi.contents = i581>>> pi.contents582c_long(99)583>>>584```585586Экземпляры указателей также можно индексировать целыми числами:587588```python589>>> pi[0]59099591>>>592```593594Присваивание целочисленному индексу изменяет значение, на которое указывает указатель:595596```python597>>> print(i)598c_long(99)599>>> pi[0] = 22600>>> print(i)601c_long(22)602>>>603```604605It is also possible to use indexes different from 0, but you must know what you’re doing, just as in C: You can access or change arbitrary memory locations. Generally you only use this feature if you receive a pointer from a C function, and you *know* that the pointer actually points to an array instead of a single item.606607Под капотом функция [`pointer()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.pointer) делает больше, чем просто создание экземпляров указателей: сначала ей нужно создать *типы* указателей. Это делается с помощью функции [`POINTER()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.POINTER), которая принимает любой тип `ctypes` и возвращает новый тип:608609```python610>>> PI = POINTER(c_int)611>>> PI612<class 'ctypes.LP_c_long'>613>>> PI(42)614Traceback (most recent call last):615  File "<stdin>", line 1, in ?616TypeError: expected c_long instead of int617>>> PI(c_int(42))618<ctypes.LP_c_long object at 0x...>619>>>620```621622Вызов типа указателя без аргумента создает нулевой указатель `NULL`. Нулевые указатели `NULL` имеют булево значение `False`:623624```python625>>> null_ptr = POINTER(c_int)()626>>> print(bool(null_ptr))627False628>>>629```630631`ctypes` проверяет на `NULL` при разыменовании указателей (но разыменование недопустимых указателей, отличных от `NULL`, приведёт к аварийному завершению Python):632633```python634>>> null_ptr[0]635Traceback (most recent call last):636    ....637ValueError: NULL pointer access638>>>639640>>> null_ptr[0] = 1234641Traceback (most recent call last):642    ....643ValueError: NULL pointer access644>>>645```646647### 15.15.1.15. Преобразования типов648649Обычно ctypes выполняет строгую проверку типов. Это означает, что если у вас есть `POINTER(c_int)` в списке `argtypes` функции или в качестве типа поля-члена в определении структуры, принимаются только экземпляры точно того же типа. Из этого правила есть некоторые исключения, когда ctypes принимает другие объекты. Например, можно передавать совместимые экземпляры массивов вместо типов указателей. Так, для `POINTER(c_int)` ctypes принимает массив c\_int:650651```python652>>> class Bar(Structure):653...     _fields_ = [("count", c_int), ("values", POINTER(c_int))]654...655>>> bar = Bar()656>>> bar.values = (c_int * 3)(1, 2, 3)657>>> bar.count = 3658>>> for i in range(bar.count):659...     print(bar.values[i])660...661166226633664>>>665```666667Чтобы установить поле типа POINTER в `NULL`, можно присвоить `None`:668669```python670>>> bar.values = None671>>>672```673674Иногда встречаются экземпляры несовместимых типов. В C можно привести один тип к другому. `ctypes` предоставляет функцию [`cast()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.cast), которую можно использовать аналогичным образом. Структура `Bar`, определённая выше, принимает указатели `POINTER(c_int)` или массивы [`c_int`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_int) для своего поля `values`, но не экземпляры других типов:675676```python677>>> bar.values = (c_byte * 4)()678Traceback (most recent call last):679  File "<stdin>", line 1, in ?680TypeError: incompatible types, c_byte_Array_4 instance instead of LP_c_long instance681>>>682```683684Для таких случаев полезна функция [`cast()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.cast).685686Функцию [`cast()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.cast) можно использовать для приведения экземпляра ctypes к указателю на другой тип данных ctypes. [`cast()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.cast) принимает два параметра: объект ctypes, который является или может быть преобразован в указатель некоторого вида, и тип указателя ctypes. Она возвращает экземпляр второго аргумента, который ссылается на тот же блок памяти, что и первый аргумент:687688```python689>>> a = (c_byte * 4)()690>>> cast(a, POINTER(c_int))691<ctypes.LP_c_long object at ...>692>>>693```694695Таким образом, [`cast()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.cast) можно использовать для присвоения полю `values` структуры `Bar`:696697```python698>>> bar = Bar()699>>> bar.values = cast((c_byte * 4)(), POINTER(c_int))700>>> print(bar.values[0])7010702>>>703```704705### 15.15.1.16. Неполные типы706707*Неполные типы* – это структуры, объединения или массивы, члены которых ещё не определены. В C они задаются опережающими объявлениями, которые определяются позже:708709```python710struct cell; /* forward declaration */711712struct {713    char *name;714    struct cell *next;715} cell;716```717718Прямой перевод в код ctypes выглядел бы так, но это не работает:719720```python721>>> class cell(Structure):722...     _fields_ = [("name", c_char_p),723...                 ("next", POINTER(cell))]724...725Traceback (most recent call last):726  File "<stdin>", line 1, in ?727  File "<stdin>", line 2, in cell728NameError: name 'cell' is not defined729>>>730```731732поскольку новый `класс cell` недоступен в самом операторе class. В `ctypes` можно определить класс `cell` и задать атрибут `_fields_` позже, после оператора class:733734```python735>>> from ctypes import *736>>> class cell(Structure):737...     pass738...739>>> cell._fields_ = [("name", c_char_p),740...                  ("next", POINTER(cell))]741>>>742```743744Попробуем. Создадим два экземпляра `cell`, заставим их указывать друг на друга и, наконец, пройдем по цепочке указателей несколько раз:745746```python747>>> c1 = cell()748>>> c1.name = "foo"749>>> c2 = cell()750>>> c2.name = "bar"751>>> c1.next = pointer(c2)752>>> c2.next = pointer(c1)753>>> p = c1754>>> for i in range(8):755...     print(p.name, end=" ")756...     p = p.next[0]757...758foo bar foo bar foo bar foo bar759>>>760```761762### 15.15.1.17. Функции обратного вызова763764`ctypes` позволяет создавать указатели на функции C из вызываемых объектов Python. Их иногда называют *функциями обратного вызова*.765766Сначала необходимо создать класс для функции обратного вызова. Этот класс знает соглашение вызова, тип возвращаемого значения, а также количество и типы аргументов, которые будет получать эта функция.767768Фабричная функция CFUNCTYPE создаёт типы для функций обратного вызова с использованием обычного соглашения вызова cdecl, а на Windows фабричная функция WINFUNCTYPE создаёт типы для функций обратного вызова с использованием соглашения вызова stdcall.769770Обе эти фабричные функции вызываются с типом результата в качестве первого аргумента, а ожидаемые типы аргументов функции обратного вызова передаются как остальные аргументы.771772Я приведу пример, в котором используется функция `qsort()` из стандартной библиотеки C; она сортирует элементы с помощью функции обратного вызова. `qsort()` будет использована для сортировки массива целых чисел:773774```python775>>> IntArray5 = c_int * 5776>>> ia = IntArray5(5, 1, 7, 33, 99)777>>> qsort = libc.qsort778>>> qsort.restype = None779>>>780```781782Функция `qsort()` должна вызываться с указателем на данные для сортировки, количеством элементов в массиве данных, размером одного элемента и указателем на функцию сравнения (обратный вызов). Затем обратный вызов будет вызван с двумя указателями на элементы; он должен возвращать отрицательное целое число, если первый элемент меньше второго, ноль, если они равны, и положительное целое число в противном случае.783784Итак, наша функция обратного вызова получает указатели на целые числа и должна возвращать целое число. Сначала создадим `тип` для функции обратного вызова:785786```python787>>> CMPFUNC = CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))788>>>789```790791Для первой реализации функции обратного вызова мы просто выводим полученные аргументы и возвращаем 0 (итеративная разработка ;-)):792793```python794>>> def py_cmp_func(a, b):795...     print("py_cmp_func", a, b)796...     return 0797...798>>>799```800801Создайте вызываемый из C обратный вызов:802803```python804>>> cmp_func = CMPFUNC(py_cmp_func)805>>>806```807808И мы готовы начать:809810```python811>>> qsort(ia, len(ia), sizeof(c_int), cmp_func) # doctest: +WINDOWS812py_cmp_func <ctypes.LP_c_long object at 0x00...> <ctypes.LP_c_long object at 0x00...>813py_cmp_func <ctypes.LP_c_long object at 0x00...> <ctypes.LP_c_long object at 0x00...>814py_cmp_func <ctypes.LP_c_long object at 0x00...> <ctypes.LP_c_long object at 0x00...>815py_cmp_func <ctypes.LP_c_long object at 0x00...> <ctypes.LP_c_long object at 0x00...>816py_cmp_func <ctypes.LP_c_long object at 0x00...> <ctypes.LP_c_long object at 0x00...>817py_cmp_func <ctypes.LP_c_long object at 0x00...> <ctypes.LP_c_long object at 0x00...>818py_cmp_func <ctypes.LP_c_long object at 0x00...> <ctypes.LP_c_long object at 0x00...>819py_cmp_func <ctypes.LP_c_long object at 0x00...> <ctypes.LP_c_long object at 0x00...>820py_cmp_func <ctypes.LP_c_long object at 0x00...> <ctypes.LP_c_long object at 0x00...>821py_cmp_func <ctypes.LP_c_long object at 0x00...> <ctypes.LP_c_long object at 0x00...>822>>>823```824825Мы знаем, как получить доступ к содержимому указателя, поэтому переопределим наш колбэк:826827```python828>>> def py_cmp_func(a, b):829...     print("py_cmp_func", a[0], b[0])830...     return 0831...832>>> cmp_func = CMPFUNC(py_cmp_func)833>>>834```835836Вот что мы получаем в Windows:837838```python839>>> qsort(ia, len(ia), sizeof(c_int), cmp_func) # doctest: +WINDOWS840py_cmp_func 7 1841py_cmp_func 33 1842py_cmp_func 99 1843py_cmp_func 5 1844py_cmp_func 7 5845py_cmp_func 33 5846py_cmp_func 99 5847py_cmp_func 7 99848py_cmp_func 33 99849py_cmp_func 7 33850>>>851```852853Забавно, что на linux функция сортировки, похоже, работает гораздо эффективнее – она делает меньше сравнений:854855```python856>>> qsort(ia, len(ia), sizeof(c_int), cmp_func) # doctest: +LINUX857py_cmp_func 5 1858py_cmp_func 33 99859py_cmp_func 7 33860py_cmp_func 5 7861py_cmp_func 1 7862>>>863```864865Ах, мы почти закончили! Последний шаг – собственно сравнить два элемента и вернуть полезный результат:866867```python868>>> def py_cmp_func(a, b):869...     print("py_cmp_func", a[0], b[0])870...     return a[0] - b[0]871...872>>>873```874875Финальный запуск в Windows:876877```python878>>> qsort(ia, len(ia), sizeof(c_int), CMPFUNC(py_cmp_func)) # doctest: +WINDOWS879py_cmp_func 33 7880py_cmp_func 99 33881py_cmp_func 5 99882py_cmp_func 1 99883py_cmp_func 33 7884py_cmp_func 1 33885py_cmp_func 5 33886py_cmp_func 5 7887py_cmp_func 1 7888py_cmp_func 5 1889>>>890```891892и в Linux:893894```python895>>> qsort(ia, len(ia), sizeof(c_int), CMPFUNC(py_cmp_func)) # doctest: +LINUX896py_cmp_func 5 1897py_cmp_func 33 99898py_cmp_func 7 33899py_cmp_func 1 7900py_cmp_func 5 7901>>>902```903904Довольно интересно, что функция `qsort()` в Windows требует больше сравнений, чем версия в linux!905906Как легко проверить, наш массив теперь отсортирован:907908```python909>>> for i in ia: print(i, end=" ")910...9111 5 7 33 99912>>>913```914915**Важное замечание для функций обратного вызова:**916917Убедитесь, что вы храните ссылки на объекты CFUNCTYPE, пока они используются из кода C. `ctypes` этого не делает, и если не хранить, они могут быть собраны сборщиком мусора, что приведёт к аварийному завершению программы при вызове колбэка.918919### 15.15.1.18. Доступ к значениям, экспортируемым из DLL920921Некоторые разделяемые библиотеки экспортируют не только функции, но и переменные. Примером в самой библиотеке Python является `Py_OptimizeFlag` – целое число, которое устанавливается в 0, 1 или 2 в зависимости от флага *-O* или *-OO*, указанного при запуске.922923`ctypes` может получать доступ к значениям подобным образом с помощью методов класса `in_dll()` типа. *pythonapi* – это предопределённый символ, предоставляющий доступ к C API Python:924925```python926>>> opt_flag = c_int.in_dll(pythonapi, "Py_OptimizeFlag")927>>> print(opt_flag)928c_long(0)929>>>930```931932Если бы интерпретатор был запущен с опцией *-O*, пример вывел бы `c_long(1)`, или `c_long(2)` если бы была указана *-OO*.933934Расширенный пример, который также демонстрирует использование указателей, обращается к указателю [`PyImport_FrozenModules`](https://python-all.ru/3.1/c-api/import.html#PyImport_FrozenModules), экспортируемому Python.935936Цитируя документацию для этого значения:937938> Этот указатель инициализируется так, чтобы указывать на массив записей939>940> `struct _frozen`941>942> , заканчивающийся записью, все члены которой равны943>944> *NULL*945>946> или нулю. Когда замороженный модуль импортируется, он ищется в этой таблице. Сторонний код может использовать это для предоставления динамически созданной коллекции замороженных модулей.947948Таким образом, манипуляции с этим указателем могут даже оказаться полезными. Чтобы ограничить размер примера, мы покажем только, как эту таблицу можно прочитать с помощью `ctypes`:949950```python951>>> from ctypes import *952>>>953>>> class struct_frozen(Structure):954...     _fields_ = [("name", c_char_p),955...                 ("code", POINTER(c_ubyte)),956...                 ("size", c_int)]957...958>>>959```960961Мы определили тип данных `struct _frozen`, поэтому можем получить указатель на таблицу:962963```python964>>> FrozenTable = POINTER(struct_frozen)965>>> table = FrozenTable.in_dll(pythonapi, "PyImport_FrozenModules")966>>>967```968969Поскольку `table` – это `указатель` на массив записей `struct_frozen`, мы можем выполнять итерацию по нему, но нужно убедиться, что цикл завершится, ведь у указателей нет размера. Рано или поздно это, вероятно, приведёт к ошибке доступа или чему-то подобному, так что лучше выйти из цикла, когда мы достигнем NULL-записи:970971```python972>>> for item in table:973...    print(item.name, item.size)974...    if item.name is None:975...        break976...977__hello__ 104978__phello__ -104979__phello__.spam 104980None 0981>>>982```983984То, что в стандартном Python есть frozen-модуль и frozen-пакет (обозначаемый отрицательным значением поля size), малоизвестно; это используется только для тестирования. Попробуйте, например, `import __hello__`.985986### 15.15.1.19. Неожиданности987988В `ctypes` есть некоторые пограничные случаи, когда поведение может отличаться от ожидаемого.989990Рассмотрим следующий пример:991992```python993>>> from ctypes import *994>>> class POINT(Structure):995...     _fields_ = ("x", c_int), ("y", c_int)996...997>>> class RECT(Structure):998...     _fields_ = ("a", POINT), ("b", POINT)999...1000>>> p1 = POINT(1, 2)1001>>> p2 = POINT(3, 4)1002>>> rc = RECT(p1, p2)1003>>> print(rc.a.x, rc.a.y, rc.b.x, rc.b.y)10041 2 3 41005>>> # теперь поменять точки местами1006>>> rc.a, rc.b = rc.b, rc.a1007>>> print(rc.a.x, rc.a.y, rc.b.x, rc.b.y)10083 4 3 41009>>>1010```10111012Хм. Мы, конечно, ожидали, что последний оператор выведет `3 4 1 2`. Что произошло? Вот шаги строки `rc.a, rc.b = rc.b, rc.a` выше:10131014```python1015>>> temp0, temp1 = rc.b, rc.a1016>>> rc.a = temp01017>>> rc.b = temp11018>>>1019```10201021Обратите внимание, что `temp0` и `temp1` – это объекты, всё ещё использующие внутренний буфер объекта `rc` выше. Таким образом, выполнение `rc.a = temp0` копирует содержимое буфера `temp0` в буфер `rc`. Это, в свою очередь, изменяет содержимое `temp1`. Поэтому последнее присваивание `rc.b = temp1` не даёт ожидаемого эффекта.10221023Имейте в виду, что получение подобъектов из Structure, Unions и Arrays не *копирует* подобъект, а возвращает объект-обертку, обращающийся к базовому буферу корневого объекта.10241025Еще один пример, который может вести себя не так, как ожидается:10261027```python1028>>> s = c_char_p()1029>>> s.value = "abc def ghi"1030>>> s.value1031'abc def ghi'1032>>> s.value is s.value1033False1034>>>1035```10361037Почему выводится `False`? Экземпляры ctypes – это объекты, содержащие блок памяти и несколько [*дескрипторов*](https://python-all.ru/3.1/glossary.html#term-descriptor) для доступа к содержимому памяти. При сохранении объекта Python в блоке памяти сохраняется не сам объект, а его `содержимое`. При каждом обращении к содержимому создаётся новый объект Python!10381039### 15.15.1.20. Типы данных переменного размера10401041`ctypes` предоставляет некоторую поддержку массивов и структур переменного размера.10421043Функция [`resize()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.resize) может использоваться для изменения размера буфера памяти существующего объекта ctypes. Функция принимает объект в качестве первого аргумента и запрошенный размер в байтах в качестве второго. Блок памяти нельзя сделать меньше, чем естественный блок памяти, заданный типом объекта; при попытке такого изменения возникает исключение [`ValueError`](https://python-all.ru/3.1/library/exceptions.html#ValueError):10441045```python1046>>> short_array = (c_short * 4)()1047>>> print(sizeof(short_array))104881049>>> resize(short_array, 4)1050Traceback (most recent call last):1051    ...1052ValueError: minimum size is 81053>>> resize(short_array, 32)1054>>> sizeof(short_array)1055321056>>> sizeof(type(short_array))105781058>>>1059```10601061Это хорошо и замечательно, но как получить доступ к дополнительным элементам, содержащимся в этом массиве? Поскольку тип по-прежнему знает только о 4 элементах, при попытке доступа к другим элементам возникают ошибки:10621063```python1064>>> short_array[:]1065[0, 0, 0, 0]1066>>> short_array[7]1067Traceback (most recent call last):1068    ...1069IndexError: invalid index1070>>>1071```10721073Другой способ использования типов данных переменного размера с `ctypes` – это воспользоваться динамической природой Python и (пере)определять тип данных после того, как необходимый размер уже известен, для каждого конкретного случая.10741075## 15.15.2. Справочник ctypes10761077### 15.15.2.1. Поиск разделяемых библиотек10781079При программировании на компилируемом языке к разделяемым библиотекам обращаются при компиляции/компоновке программы и при ее запуске.10801081Назначение функции `find_library()` – найти библиотеку способом, аналогичным тому, как это делает компилятор (на платформах с несколькими версиями разделяемой библиотеки должна загружаться самая новая), в то время как загрузчики библиотек ctypes действуют как при запуске программы и вызывают загрузчик времени выполнения напрямую.10821083Модуль `ctypes.util` предоставляет функцию, которая может помочь определить, какую библиотеку загрузить.10841085#### `ctypes.util.find_library(name)`10861087Пытается найти библиотеку и возвращает путь к ней.10881089*name*10901091– это имя библиотеки без префикса вроде10921093*lib*10941095, суффикса вроде10961097`.so`10981099,11001101`.dylib`11021103или номера версии (это форма, используемая для опции компоновщика posix11041105[*-l*](https://python-all.ru/3.1/library/compileall.html#cmdoption-compileall-l)11061107). Если библиотека не найдена, возвращается11081109`None`11101111.11121113Точное поведение зависит от системы.11141115В Linux `find_library()` пытается запустить внешние программы (`/sbin/ldconfig`, `gcc` и `objdump`), чтобы найти файл библиотеки. Возвращается имя файла библиотеки. Вот несколько примеров:11161117```python1118>>> from ctypes.util import find_library1119>>> find_library("m")1120'libm.so.6'1121>>> find_library("c")1122'libc.so.6'1123>>> find_library("bz2")1124'libbz2.so.1.0'1125>>>1126```11271128В OS X `find_library()` пробует несколько предопределённых схем именования и путей для поиска библиотеки и возвращает полный путь в случае успеха:11291130```python1131>>> from ctypes.util import find_library1132>>> find_library("c")1133'/usr/lib/libc.dylib'1134>>> find_library("m")1135'/usr/lib/libm.dylib'1136>>> find_library("bz2")1137'/usr/lib/libbz2.dylib'1138>>> find_library("AGL")1139'/System/Library/Frameworks/AGL.framework/AGL'1140>>>1141```11421143В Windows `find_library()` выполняет поиск по системному пути поиска и возвращает полный путь, но поскольку нет предопределённой схемы именования, вызов вроде `find_library("c")` завершится ошибкой и вернёт `None`.11441145Если вы оборачиваете разделяемую библиотеку с помощью `ctypes`, *возможно*, лучше определить имя разделяемой библиотеки на этапе разработки и жёстко закодировать его в модуль-обёртку, вместо использования `find_library()` для поиска библиотеки во время выполнения.11461147### 15.15.2.2. Загрузка разделяемых библиотек11481149Существует несколько способов загрузить разделяемые библиотеки в процесс Python. Один из способов – создать экземпляр одного из следующих классов:11501151#### `class ctypes.CDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False)`11521153Экземпляры этого класса представляют загруженные разделяемые библиотеки. Функции в этих библиотеках используют стандартное соглашение о вызове C и считаются возвращающими11541155`int`11561157.11581159#### `class ctypes.OleDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False)`11601161Только для Windows: экземпляры этого класса представляют загруженные разделяемые библиотеки; функции в этих библиотеках используют соглашение о вызове11621163`stdcall`11641165и, как предполагается, возвращают специфичный для Windows код11661167[`HRESULT`](https://python-all.ru/3.1/library/ctypes.html#ctypes.HRESULT)11681169. Значения11701171[`HRESULT`](https://python-all.ru/3.1/library/ctypes.html#ctypes.HRESULT)11721173содержат информацию, указывающую, успешно ли завершился вызов функции или произошла ошибка, вместе с дополнительным кодом ошибки. Если возвращаемое значение сигнализирует об ошибке, автоматически возбуждается исключение11741175[`WindowsError`](https://python-all.ru/3.1/library/exceptions.html#WindowsError)11761177.11781179#### `class ctypes.WinDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False)`11801181Только для Windows: экземпляры этого класса представляют загруженные разделяемые библиотеки, функции в этих библиотеках используют соглашение о вызове `stdcall` и по умолчанию предполагается, что они возвращают `int`.11821183На Windows CE используется только стандартное соглашение о вызове; для удобства [`WinDLL`](https://python-all.ru/3.1/library/ctypes.html#ctypes.WinDLL) и [`OleDLL`](https://python-all.ru/3.1/library/ctypes.html#ctypes.OleDLL) на этой платформе используют стандартное соглашение о вызове.11841185Глобальная блокировка интерпретатора Python [*global interpreter lock*](https://python-all.ru/3.1/glossary.html#term-global-interpreter-lock) освобождается перед вызовом любой функции, экспортируемой этими библиотеками, и снова захватывается после вызова.11861187#### `class ctypes.PyDLL(name, mode=DEFAULT_MODE, handle=None)`11881189Экземпляры этого класса ведут себя как экземпляры [`CDLL`](https://python-all.ru/3.1/library/ctypes.html#ctypes.CDLL), за исключением того, что GIL Python *не* освобождается при вызове функции, а после выполнения функции проверяется флаг ошибок Python. Если флаг ошибок установлен, возбуждается исключение Python.11901191Таким образом, это полезно только для прямого вызова функций Python C API.11921193Все эти классы можно создать, вызвав их с хотя бы одним аргументом – именем пути разделяемой библиотеки. Если у вас уже есть дескриптор загруженной разделяемой библиотеки, его можно передать в качестве именованного параметра `handle`; в противном случае для загрузки библиотеки в процесс и получения её дескриптора используются функции базовой платформы `dlopen` или `LoadLibrary`.11941195Параметр *mode* можно использовать для указания способа загрузки библиотеки. Подробнее см. страницу руководства *dlopen(3)*; в Windows параметр *mode* игнорируется.11961197Параметр *use\_errno* при установке в True включает механизм ctypes, который позволяет безопасно получать доступ к системному коду ошибки `errno`. `ctypes` хранит потоко-локальную копию системной переменной `errno`; если вызвать внешние функции, созданные с `use_errno=True`, то значение `errno` перед вызовом функции заменяется на приватную копию ctypes, и то же самое происходит сразу после вызова функции.11981199Функция [`ctypes.get_errno()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.get_errno) возвращает значение частной копии ctypes, а функция [`ctypes.set_errno()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.set_errno) изменяет частную копию ctypes на новое значение и возвращает предыдущее значение.12001201Параметр *use\_last\_error*, если установлен в True, включает тот же механизм для кода ошибки Windows, который управляется функциями Windows API [`GetLastError()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.GetLastError) и `SetLastError()`; функции [`ctypes.get_last_error()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.get_last_error) и [`ctypes.set_last_error()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.set_last_error) используются для получения и изменения частной копии кода ошибки Windows в ctypes.12021203#### `ctypes.RTLD_GLOBAL`12041205Флаг, используемый в качестве параметра12061207*mode*12081209. На платформах, где этот флаг недоступен, он определён как целочисленный ноль.12101211#### `ctypes.RTLD_LOCAL`12121213Флаг, используемый в качестве параметра12141215*mode*12161217. На платформах, где он недоступен, он совпадает с12181219*RTLD\_GLOBAL*12201221.12221223#### `ctypes.DEFAULT_MODE`12241225Режим по умолчанию, используемый для загрузки разделяемых библиотек. На OSX 10.3 это12261227*RTLD\_GLOBAL*12281229, в противном случае он совпадает с12301231*RTLD\_LOCAL*12321233.12341235Экземпляры этих классов не имеют открытых методов, однако [`__getattr__()`](https://python-all.ru/3.1/reference/datamodel.html#object.__getattr__) и [`__getitem__()`](https://python-all.ru/3.1/reference/datamodel.html#object.__getitem__) обладают особым поведением: функции, экспортируемые общей библиотекой, могут быть доступны как атрибуты или по индексу. Обратите внимание, что оба [`__getattr__()`](https://python-all.ru/3.1/reference/datamodel.html#object.__getattr__) и [`__getitem__()`](https://python-all.ru/3.1/reference/datamodel.html#object.__getitem__) кешируют свой результат, поэтому повторные вызовы возвращают один и тот же объект.12361237Доступны следующие открытые атрибуты, их имена начинаются с подчёркивания, чтобы не конфликтовать с именами экспортируемых функций:12381239#### `PyDLL._handle`12401241Системный дескриптор, используемый для доступа к библиотеке.12421243#### `PyDLL._name`12441245Имя библиотеки, переданное в конструктор.12461247Разделяемые библиотеки также можно загружать с помощью одного из предварительно созданных объектов, которые являются экземплярами класса [`LibraryLoader`](https://python-all.ru/3.1/library/ctypes.html#ctypes.LibraryLoader), либо вызывая метод `LoadLibrary()`, либо получая библиотеку как атрибут экземпляра загрузчика.12481249#### `class ctypes.LibraryLoader(dlltype)`12501251Класс, который загружает разделяемые библиотеки. *dlltype* должен быть одним из типов [`CDLL`](https://python-all.ru/3.1/library/ctypes.html#ctypes.CDLL), [`PyDLL`](https://python-all.ru/3.1/library/ctypes.html#ctypes.PyDLL), [`WinDLL`](https://python-all.ru/3.1/library/ctypes.html#ctypes.WinDLL) или [`OleDLL`](https://python-all.ru/3.1/library/ctypes.html#ctypes.OleDLL).12521253[`__getattr__()`](https://python-all.ru/3.1/reference/datamodel.html#object.__getattr__) обладает особым поведением: позволяет загрузить разделяемую библиотеку, обращаясь к ней как к атрибуту экземпляра загрузчика библиотек. Результат кэшируется, поэтому повторные обращения к атрибуту каждый раз возвращают ту же библиотеку.12541255#### `LoadLibrary(name)`12561257Загружает разделяемую библиотеку в процесс и возвращает её. Этот метод всегда возвращает новый экземпляр библиотеки.12581259Доступны следующие готовые загрузчики библиотек:12601261#### `ctypes.cdll`12621263Создаёт экземпляры12641265[`CDLL`](https://python-all.ru/3.1/library/ctypes.html#ctypes.CDLL)12661267.12681269#### `ctypes.windll`12701271Только для Windows: создаёт экземпляры12721273[`WinDLL`](https://python-all.ru/3.1/library/ctypes.html#ctypes.WinDLL)12741275.12761277#### `ctypes.oledll`12781279Только для Windows: создаёт экземпляры12801281[`OleDLL`](https://python-all.ru/3.1/library/ctypes.html#ctypes.OleDLL)12821283.12841285#### `ctypes.pydll`12861287Создаёт экземпляры12881289[`PyDLL`](https://python-all.ru/3.1/library/ctypes.html#ctypes.PyDLL)12901291.12921293Для прямого доступа к C Python API доступен готовый к использованию объект общей библиотеки Python:12941295#### `ctypes.pythonapi`12961297Экземпляр12981299[`PyDLL`](https://python-all.ru/3.1/library/ctypes.html#ctypes.PyDLL)13001301, который предоставляет функции C API Python в качестве атрибутов. Обратите внимание, что все эти функции предполагаются возвращающими13021303`int`13041305(C int), что, конечно, не всегда верно, поэтому для их использования необходимо задать правильный атрибут13061307`restype`13081309.13101311### 15.15.2.3. Внешние функции13121313Как объяснялось в предыдущем разделе, внешние функции можно получить как атрибуты загруженных разделяемых библиотек. Созданные таким образом объекты функций по умолчанию принимают любое количество аргументов, принимают любые экземпляры данных ctypes в качестве аргументов и возвращают тип результата по умолчанию, указанный загрузчиком библиотеки. Они являются экземплярами закрытого класса:13141315#### `class ctypes._FuncPtr`13161317Базовый класс для внешних функций, вызываемых из C.13181319Экземпляры внешних функций также являются C-совместимыми типами данных; они представляют указатели на функции C.13201321Это поведение можно настроить, присвоив значения специальным атрибутам объекта внешней функции.13221323#### `restype`13241325Присваивает тип ctypes для указания типа результата внешней функции. Используйте `None` для `void` – функции, ничего не возвращающей.13261327Можно назначить вызываемый объект Python, который не является типом ctypes; в этом случае предполагается, что функция возвращает C `int`, и вызываемый объект будет вызван с этим целым числом, что позволяет выполнить дальнейшую обработку или проверку ошибок. Использование этого устарело; для более гибкой постобработки или проверки ошибок используйте тип данных ctypes как [`restype`](https://python-all.ru/3.1/library/ctypes.html#ctypes._FuncPtr.restype) и назначьте вызываемый объект атрибуту [`errcheck`](https://python-all.ru/3.1/library/ctypes.html#ctypes._FuncPtr.errcheck).13281329#### `argtypes`13301331Назначьте кортеж типов ctypes, чтобы указать типы аргументов, которые принимает функция. Функции, использующие соглашение о вызове `stdcall`, могут быть вызваны только с тем же количеством аргументов, что и длина этого кортежа; функции, использующие соглашение о вызове C, также принимают дополнительные неуказанные аргументы.13321333Когда вызывается внешняя функция, каждый фактический аргумент передаётся методу класса `from_param()` элементов кортежа [`argtypes`](https://python-all.ru/3.1/library/ctypes.html#ctypes._FuncPtr.argtypes); этот метод позволяет адаптировать фактический аргумент к объекту, который принимает внешняя функция. Например, элемент [`c_char_p`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_char_p) в кортеже [`argtypes`](https://python-all.ru/3.1/library/ctypes.html#ctypes._FuncPtr.argtypes) преобразует строку, переданную как аргумент, в объект bytes, используя правила преобразования ctypes.13341335Новое: теперь можно помещать в argtypes элементы, которые не являются типами ctypes, но каждый элемент должен иметь метод `from_param()`, возвращающий значение, пригодное для использования в качестве аргумента (целое число, строка, экземпляр ctypes). Это позволяет определять адаптеры, которые могут адаптировать пользовательские объекты как параметры функции.13361337#### `errcheck`13381339Этому атрибуту присваивается функция Python или другой вызываемый объект. Вызываемый объект будет вызван с тремя и более аргументами:13401341#### `callable(result, func, arguments)`13421343*result* – это то, что возвращает внешняя функция, как указано атрибутом [`restype`](https://python-all.ru/3.1/library/ctypes.html#ctypes._FuncPtr.restype).13441345*func* – это сам объект внешней функции; это позволяет повторно использовать один и тот же вызываемый объект для проверки или постобработки результатов нескольких функций.13461347*arguments* – это кортеж, содержащий параметры, изначально переданные при вызове функции; это позволяет специализировать поведение в зависимости от использованных аргументов.13481349Объект, возвращаемый этой функцией, будет возвращён из вызова внешней функции, но он также может проверить значение результата и возбудить исключение, если вызов внешней функции завершился неудачей.13501351#### `exception ctypes.ArgumentError`13521353Это исключение возникает, когда вызов внешней функции не может преобразовать один из переданных аргументов.13541355### 15.15.2.4. Прототипы функций13561357Внешние функции также можно создать, инстанцируя прототипы функций. Прототипы функций аналогичны прототипам функций в C; они описывают функцию (тип возвращаемого значения, типы аргументов, соглашение о вызове) без определения реализации. Фабричные функции необходимо вызывать с желаемым типом результата и типами аргументов функции.13581359#### `ctypes.CFUNCTYPE(restype, *argtypes, use_errno=False, use_last_error=False)`13601361Возвращаемый прототип функции создаёт функции, использующие стандартное соглашение о вызовах C. Функция освобождает GIL во время вызова. Если13621363*use\_errno*13641365установлен в True, частная копия системной переменной13661367`errno`13681369из ctypes обменивается с реальным значением13701371`errno`13721373до и после вызова;13741375*use\_last\_error*13761377делает то же самое для кода ошибки Windows.13781379#### `ctypes.WINFUNCTYPE(restype, *argtypes, use_errno=False, use_last_error=False)`13801381Только для Windows: возвращаемый прототип функции создаёт функции, использующие соглашение о вызове13821383`stdcall`13841385, за исключением Windows CE, где13861387[`WINFUNCTYPE()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.WINFUNCTYPE)13881389совпадает с13901391[`CFUNCTYPE()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.CFUNCTYPE)13921393. Функция освобождает GIL во время вызова.13941395*use\_errno*13961397и13981399*use\_last\_error*14001401имеют тот же смысл, что и выше.14021403#### `ctypes.PYFUNCTYPE(restype, *argtypes)`14041405Созданный прототип функции создаёт функции, использующие соглашение о вызове Python. Функция14061407*не*14081409освобождает GIL во время вызова.14101411Прототипы функций, созданные этими фабричными функциями, могут быть созданы различными способами, в зависимости от типа и количества параметров в вызове:14121413> #### `prototype(address)`1414>1415> Возвращает внешнюю функцию по указанному адресу, который должен быть целым числом.1416>1417> #### `prototype(callable)`1418>1419> Создаёт вызываемую функцию C (функцию обратного вызова) из1420>1421> *вызываемого объекта*1422>1423> Python.1424>1425> #### `prototype(func_spec[, paramflags])`1426>1427> Возвращает внешнюю функцию, экспортируемую общей библиотекой.1428>1429> *func\_spec*1430>1431> должен быть кортежем из двух элементов1432>1433> `(name_or_ordinal, library)`1434>1435> . Первый элемент – это имя экспортируемой функции в виде строки или её порядковый номер (ординал) в виде небольшого целого числа. Второй элемент – это экземпляр общей библиотеки.1436>1437> #### `prototype(vtbl_index, name[, paramflags[, iid]])`1438>1439> Возвращает внешнюю функцию, которая будет вызывать метод COM. *vtbl\_index* – это индекс в таблице виртуальных функций, небольшое неотрицательное целое число. *name* – это имя метода COM. *iid* – необязательный указатель на идентификатор интерфейса, используемый в расширенном отчёте об ошибках.1440>1441> Методы COM используют специальное соглашение о вызове: они требуют указатель на интерфейс COM в качестве первого аргумента, в дополнение к тем параметрам, которые указаны в кортеже `argtypes`.1442>1443> Необязательный параметр *paramflags* создаёт обёртки внешних функций с гораздо большей функциональностью, чем описано выше.1444>1445> *paramflags* должен быть кортежем той же длины, что и `argtypes`.1446>1447> Каждый элемент этого кортежа содержит дополнительную информацию о параметре; он должен быть кортежем, содержащим один, два или три элемента.1448>1449> Первый элемент – целое число, содержащее комбинацию флагов направления для параметра:1450>1451> > **1**1452> >1453> > Задаёт входной параметр функции.1454> >1455> > **2**1456> >1457> > Выходной параметр. Внешняя функция заполняет значение.1458> >1459> > **4**1460> >1461> > Входной параметр, по умолчанию равный нулю.1462>1463> Необязательный второй элемент – имя параметра в виде строки. Если он указан, внешнюю функцию можно вызывать с именованными параметрами.1464>1465> Необязательный третий элемент – значение по умолчанию для этого параметра.14661467Этот пример демонстрирует, как обернуть функцию Windows `MessageBoxA` так, чтобы она поддерживала параметры по умолчанию и именованные аргументы. Объявление C из заголовочного файла Windows выглядит так:14681469```python1470WINUSERAPI int WINAPI1471MessageBoxA(1472    HWND hWnd ,1473    LPCSTR lpText,1474    LPCSTR lpCaption,1475    UINT uType);1476```14771478Вот обёртка с помощью `ctypes`:14791480```python1481>>> from ctypes import c_int, WINFUNCTYPE, windll1482>>> from ctypes.wintypes import HWND, LPCSTR, UINT1483>>> prototype = WINFUNCTYPE(c_int, HWND, LPCSTR, LPCSTR, UINT)1484>>> paramflags = (1, "hwnd", 0), (1, "text", "Hi"), (1, "caption", None), (1, "flags", 0)1485>>> MessageBox = prototype(("MessageBoxA", windll.user32), paramflags)1486>>>1487```14881489Теперь внешнюю функцию MessageBox можно вызывать следующими способами:14901491```python1492>>> MessageBox()1493>>> MessageBox(text="Spam, spam, spam")1494>>> MessageBox(flags=2, text="foo bar")1495>>>1496```14971498Второй пример демонстрирует выходные параметры. Функция win32 `GetWindowRect` получает размеры указанного окна, копируя их в структуру `RECT`, которую должен предоставить вызывающий код. Вот объявление C:14991500```python1501WINUSERAPI BOOL WINAPI1502GetWindowRect(1503     HWND hWnd,1504     LPRECT lpRect);1505```15061507Вот обёртка с помощью `ctypes`:15081509```python1510>>> from ctypes import POINTER, WINFUNCTYPE, windll, WinError1511>>> from ctypes.wintypes import BOOL, HWND, RECT1512>>> prototype = WINFUNCTYPE(BOOL, HWND, POINTER(RECT))1513>>> paramflags = (1, "hwnd"), (2, "lprect")1514>>> GetWindowRect = prototype(("GetWindowRect", windll.user32), paramflags)1515>>>1516```15171518Функции с выходными параметрами автоматически возвращают значение выходного параметра, если он один, или кортеж значений выходных параметров, если их несколько; таким образом, при вызове функция GetWindowRect теперь возвращает экземпляр RECT.15191520Выходные параметры можно комбинировать с протоколом `errcheck` для дальнейшей обработки вывода и проверки ошибок. Функция win32 API `GetWindowRect` возвращает `BOOL` для сигнализации об успехе или неудаче, поэтому эта функция могла бы выполнять проверку ошибок и возбуждать исключение при сбое вызова API:15211522```python1523>>> def errcheck(result, func, args):1524...     if not result:1525...         raise WinError()1526...     return args1527...1528>>> GetWindowRect.errcheck = errcheck1529>>>1530```15311532Если функция `errcheck` возвращает кортеж аргументов, который она получила, без изменений, `ctypes` продолжает обычную обработку выходных параметров. Если требуется вернуть кортеж координат окна вместо экземпляра `RECT`, можно извлечь поля в функции и вернуть их; обычная обработка выполняться не будет.15331534```python1535>>> def errcheck(result, func, args):1536...     if not result:1537...         raise WinError()1538...     rc = args[1]1539...     return rc.left, rc.top, rc.bottom, rc.right1540...1541>>> GetWindowRect.errcheck = errcheck1542>>>1543```15441545### 15.15.2.5. Вспомогательные функции15461547#### `ctypes.addressof(obj)`15481549Возвращает адрес буфера памяти в виде целого числа.15501551*obj*15521553должен быть экземпляром типа ctypes.15541555#### `ctypes.alignment(obj_or_type)`15561557Возвращает требования к выравниванию для типа ctypes.15581559*obj\_or\_type*15601561должен быть типом ctypes или его экземпляром.15621563#### `ctypes.byref(obj[, offset])`15641565Возвращает легковесный указатель на *obj*, который должен быть экземпляром типа ctypes. Параметр *offset* по умолчанию равен нулю и должен быть целым числом, которое будет добавлено к внутреннему значению указателя.15661567`byref(obj, offset)` соответствует следующему коду на C:15681569```python1570(((char *)&obj) + offset)1571```15721573Возвращаемый объект можно использовать только как параметр вызова внешней функции. Он ведёт себя аналогично `pointer(obj)`, но создаётся намного быстрее.15741575#### `ctypes.cast(obj, type)`15761577Эта функция аналогична оператору приведения типов в C. Она возвращает новый экземпляр15781579*type*15801581, указывающий на тот же блок памяти, что и15821583*obj*15841585.15861587*type*15881589должен быть типом-указателем, а15901591*obj*15921593– объектом, который можно интерпретировать как указатель.15941595#### `ctypes.create_string_buffer(init_or_size, size=None)`15961597Эта функция создаёт изменяемый символьный буфер. Возвращаемый объект – это массив ctypes из [`c_char`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_char).15981599*init\_or\_size* должен быть целым числом, задающим размер массива, или объектом bytes, который будет использоваться для инициализации элементов массива.16001601Если первым аргументом указан объект bytes, буфер создаётся на один элемент больше его длины, чтобы последним элементом массива был нулевой символ (NUL). Вторым аргументом можно передать целое число, которое позволяет задать размер массива, если длина bytes не должна использоваться.16021603Если первый параметр является строкой, она преобразуется в объект bytes в соответствии с правилами преобразования ctypes.16041605#### `ctypes.create_unicode_buffer(init_or_size, size=None)`16061607Эта функция создаёт изменяемый буфер символов Unicode. Возвращаемый объект – это массив ctypes из [`c_wchar`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_wchar).16081609*init\_or\_size* должен быть целым числом, задающим размер массива, или строкой, которая будет использоваться для инициализации элементов массива.16101611Если первым аргументом указана строка, буфер создаётся на один элемент больше её длины, чтобы последним элементом массива был нулевой символ (NUL). Вторым аргументом можно передать целое число, которое позволяет задать размер массива, если длина строки не должна использоваться.16121613Если первый параметр является объектом bytes, он преобразуется в строку unicode в соответствии с правилами преобразования ctypes.16141615#### `ctypes.DllCanUnloadNow()`16161617Только Windows: эта функция является хуком, который позволяет реализовать внутрипроцессные COM-серверы с помощью ctypes. Она вызывается из функции DllCanUnloadNow, которую экспортирует DLL расширения \_ctypes.16181619#### `ctypes.DllGetClassObject()`16201621Только Windows: эта функция является хуком, который позволяет реализовать внутрипроцессные COM-серверы с помощью ctypes. Она вызывается из функции DllGetClassObject, которую экспортирует DLL расширения16221623`_ctypes`16241625.16261627#### `ctypes.util.find_library(name)`16281629Пытается найти библиотеку и возвращает путь к ней. *name* – это имя библиотеки без префикса вроде `lib`, суффикса вроде `.so`, `.dylib` или номера версии (такая форма используется для опции компоновщика POSIX [*-l*](https://python-all.ru/3.1/library/compileall.html#cmdoption-compileall-l)). Если библиотека не найдена, возвращается `None`.16301631Точное поведение зависит от системы.16321633#### `ctypes.util.find_msvcrt()`16341635Только для Windows: возвращает имя файла библиотеки времени выполнения VC, используемой Python и модулями расширения. Если имя библиотеки не удаётся определить, возвращается `None`.16361637Если необходимо освободить память, выделенную, например, модулем расширения с помощью вызова `free(void *)`, важно использовать функцию из той же библиотеки, которая выделила память.16381639#### `ctypes.FormatError([code])`16401641Только для Windows: возвращает текстовое описание кода ошибки16421643*code*16441645. Если код ошибки не указан, используется последний код ошибки, полученный вызовом функции Windows API GetLastError.16461647#### `ctypes.GetLastError()`16481649Только для Windows: Возвращает последний код ошибки, установленный Windows в вызывающем потоке. Эта функция вызывает непосредственно функцию Windows16501651*GetLastError()*16521653; она не возвращает внутреннюю для ctypes копию кода ошибки.16541655#### `ctypes.get_errno()`16561657Возвращает текущее значение принадлежащей ctypes копии системной переменной16581659`errno`16601661в вызывающем потоке.16621663#### `ctypes.get_last_error()`16641665Только Windows: возвращает текущее значение переменной16661667`LastError`16681669(приватной копии ctypes системной переменной LastError) в вызывающем потоке.16701671#### `ctypes.memmove(dst, src, count)`16721673Аналогична стандартной библиотечной функции C memmove: копирует16741675*count*16761677байт из16781679*src*16801681в16821683*dst*16841685.16861687*dst*16881689и16901691*src*16921693должны быть целыми числами или экземплярами ctypes, которые можно преобразовать в указатели.16941695#### `ctypes.memset(dst, c, count)`16961697Аналогична стандартной библиотечной функции C memset: заполняет блок памяти по адресу16981699*dst*17001701*count*17021703байтами значения17041705*c*17061707.17081709*dst*17101711должно быть целым числом, задающим адрес, или экземпляром ctypes.17121713#### `ctypes.POINTER(type)`17141715Эта фабричная функция создаёт и возвращает новый тип указателя ctypes. Типы указателей кэшируются и повторно используются внутри, поэтому многократный вызов этой функции не требует больших затрат.17161717*type*17181719должен быть типом ctypes.17201721#### `ctypes.pointer(obj)`17221723Эта функция создаёт новый экземпляр указателя, указывающий на *obj*. Возвращаемый объект имеет тип `POINTER(type(obj))`.17241725Примечание: если нужно просто передать указатель на объект в вызов внешней функции, используйте `byref(obj)` – это намного быстрее.17261727#### `ctypes.resize(obj, size)`17281729Эта функция изменяет размер внутреннего буфера памяти объекта17301731*obj*17321733, который должен быть экземпляром типа ctypes. Невозможно сделать буфер меньше, чем собственный размер типа объекта, задаваемый выражением17341735`sizeof(type(obj))`17361737, но можно его увеличить.17381739#### `ctypes.set_conversion_mode(encoding, errors)`17401741Эта функция задаёт правила, которые объекты ctypes используют при преобразовании между объектами bytes и (unicode) строками. *encoding* должна быть строкой, задающей кодировку, например `'utf-8'` или `'mbcs'`, *errors* должна быть строкой, задающей обработку ошибок при кодировании/декодировании. Примеры возможных значений: `'strict'`, `'replace'` или `'ignore'`.17421743[`set_conversion_mode()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.set_conversion_mode) возвращает кортеж из двух элементов, содержащий предыдущие правила преобразования. В Windows начальные правила преобразования: `('mbcs', 'ignore')`, в других системах – `('ascii', 'strict')`.17441745Можно установить *encoding* в `'undefined'`, чтобы полностью отключить автоматическое преобразование.17461747#### `ctypes.set_errno(value)`17481749Устанавливает текущее значение принадлежащей ctypes копии системной переменной17501751`errno`17521753в вызывающем потоке равным17541755*value*17561757и возвращает предыдущее значение.17581759#### `ctypes.set_last_error(value)`17601761Только для Windows: устанавливает текущее значение приватной копии системной переменной17621763`LastError`17641765в вызывающем потоке в17661767*value*17681769и возвращает предыдущее значение.17701771#### `ctypes.sizeof(obj_or_type)`17721773Возвращает размер в байтах буфера памяти ctypes-типа или экземпляра. Делает tо же самое, что и функция C17741775`sizeof()`17761777.17781779#### `ctypes.string_at(address, size=-1)`17801781Эта функция возвращает C-строку, начинающуюся с адреса памяти address, в виде объекта bytes. Если указан size, он используется как размер, в противном случае строка считается завершающейся нулём.17821783#### `ctypes.WinError(code=None, descr=None)`17841785Только для Windows: эта функция, вероятно, самая неудачно названная вещь в ctypes. Она создаёт экземпляр WindowsError. Если17861787*code*17881789не указан, вызывается17901791`GetLastError`17921793для определения кода ошибки. Если17941795*descr*17961797не указан, вызывается17981799[`FormatError()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.FormatError)18001801для получения текстового описания ошибки.18021803#### `ctypes.wstring_at(address, size=-1)`18041805Эта функция возвращает строку широких символов, начинающуюся по адресу памяти18061807*address*18081809, в виде строки. Если указан18101811*size*18121813, он используется как количество символов строки, в противном случае строка считается завершающейся нулевым символом.18141815### 15.15.2.6. Типы данных18161817#### `class ctypes._CData`18181819Этот непубличный класс является общим базовым классом для всех типов данных ctypes. Среди прочего, все экземпляры типов ctypes содержат блок памяти, который хранит данные, совместимые с C; адрес блока памяти возвращается вспомогательной функцией [`addressof()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.addressof). Ещё одна переменная экземпляра представлена как [`_objects`](https://python-all.ru/3.1/library/ctypes.html#ctypes._CData._objects); она содержит другие объекты Python, которые необходимо сохранять в памяти на случай, если блок памяти содержит указатели.18201821Общие методы типов данных ctypes, все они являются методами класса (если точнее, это методы [*метакласса*](https://python-all.ru/3.1/glossary.html#term-metaclass)):18221823#### `from_buffer(source[, offset])`18241825Этот метод возвращает экземпляр ctypes, который использует тот же буфер, что и объект18261827*source*18281829. Объект18301831*source*18321833должен поддерживать интерфейс буфера с возможностью записи. Необязательный параметр18341835*offset*18361837задаёт смещение в байтах внутри буфера источника; по умолчанию – ноль. Если буфер источника недостаточно велик, возникает исключение18381839[`ValueError`](https://python-all.ru/3.1/library/exceptions.html#ValueError)18401841.18421843#### `from_buffer_copy(source[, offset])`18441845Этот метод создаёт экземпляр ctypes, копируя буфер из объекта18461847*source*18481849, который должен быть доступен для чтения. Необязательный параметр18501851*offset*18521853задаёт смещение в байтах внутри буфера источника; по умолчанию – ноль. Если буфер источника недостаточно велик, возникает исключение18541855[`ValueError`](https://python-all.ru/3.1/library/exceptions.html#ValueError)18561857.18581859#### `from_address(address)`18601861Этот метод возвращает экземпляр типа ctypes, использующий память, указанную18621863*address*18641865, который должен быть целым числом.18661867#### `from_param(obj)`18681869Этот метод приводит *obj* к типу ctypes. Он вызывается с фактическим объектом, используемым в вызове внешней функции, когда тип присутствует в кортеже `argtypes` этой функции; он должен вернуть объект, который можно использовать в качестве параметра вызова функции.18701871Все типы данных ctypes имеют реализацию этого метода класса по умолчанию, которая обычно возвращает *obj*, если он является экземпляром этого типа. Некоторые типы также принимают другие объекты.18721873#### `in_dll(library, name)`18741875Этот метод возвращает экземпляр типа ctypes, экспортируемый общей библиотекой.18761877*name*18781879– это имя символа, экспортирующего данные;18801881*library*18821883– загруженная общая библиотека.18841885Общие переменные экземпляра типов данных ctypes:18861887#### `_b_base_`18881889Иногда экземпляры данных ctypes не владеют блоком памяти, который содержат, а вместо этого разделяют часть блока памяти базового объекта. Член только для чтения18901891[`_b_base_`](https://python-all.ru/3.1/library/ctypes.html#ctypes._CData._b_base_)18921893является корневым объектом ctypes, которому принадлежит блок памяти.18941895#### `_b_needsfree_`18961897Эта переменная только для чтения равна true, когда экземпляр данных ctypes сам выделил блок памяти, и false в противном случае.18981899#### `_objects`19001901Этот член может быть либо19021903`None`19041905, либо словарём, содержащим объекты Python, которые необходимо сохранять в памяти, чтобы содержимое блока памяти оставалось корректным. Этот объект предоставляется только для отладки; никогда не изменяйте содержимое этого словаря.19061907### 15.15.2.7. Фундаментальные типы данных19081909#### `class ctypes._SimpleCData`19101911Этот непубличный класс является базовым классом для всех фундаментальных типов данных ctypes. Он упоминается здесь, потому что содержит общие атрибуты фундаментальных типов данных ctypes. [`_SimpleCData`](https://python-all.ru/3.1/library/ctypes.html#ctypes._SimpleCData) является подклассом [`_CData`](https://python-all.ru/3.1/library/ctypes.html#ctypes._CData), поэтому наследует их методы и атрибуты. Типы данных ctypes, которые не являются указателями и не содержат указателей, теперь можно сериализовать.19121913Экземпляры имеют один атрибут:19141915#### `value`19161917Этот атрибут содержит фактическое значение экземпляра. Для целочисленных типов и типов указателей это целое число, для символьных типов – объект bytes из одного символа или строка, для символьных указателей – объект Python bytes или строка.19181919Когда атрибут `value` извлекается из экземпляра ctypes, обычно каждый раз возвращается новый объект. `ctypes` *не* реализует возврат исходного объекта – всегда создается новый. То же самое верно для всех остальных экземпляров объектов ctypes.19201921Базовые типы данных при возврате из вызовов внешних функций или, например, при получении полей структур или элементов массивов прозрачно преобразуются в нативные типы Python. Иными словами, если внешняя функция имеет `restype` [`c_char_p`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_char_p), вы всегда получите объект Python bytes, *а не* экземпляр [`c_char_p`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_char_p).19221923Подклассы базовых типов данных *не* наследуют это поведение. Так, если `restype` внешней функции является подклассом [`c_void_p`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_void_p), то из вызова функции вы получите экземпляр этого подкласса. Разумеется, значение указателя можно получить, обратившись к атрибуту `value`.19241925Вот фундаментальные типы данных ctypes:19261927#### `class ctypes.c_byte`19281929Представляет тип данных C19301931`signed char`19321933и интерпретирует значение как небольшое целое число. Конструктор принимает необязательный инициализатор целого типа; проверка переполнения не выполняется.19341935#### `class ctypes.c_char`19361937Представляет тип данных C19381939`char`19401941и интерпретирует значение как один символ. Конструктор принимает необязательный строковый инициализатор; длина строки должна быть ровно один символ.19421943#### `class ctypes.c_char_p`19441945Представляет тип данных C19461947`char *`19481949, когда он указывает на строку, завершающуюся нулевым символом. Для обычного указателя на символ, который может также указывать на бинарные данные, следует использовать19501951`POINTER(c_char)`19521953. Конструктор принимает целочисленный адрес или объект bytes.19541955#### `class ctypes.c_double`19561957Представляет тип данных C19581959`double`19601961. Конструктор принимает необязательный инициализатор с плавающей запятой.19621963#### `class ctypes.c_longdouble`19641965Представляет тип данных C19661967`long double`19681969. Конструктор принимает необязательный инициализатор с плавающей запятой. На платформах, где19701971`sizeof(long double) == sizeof(double)`19721973, он является псевдонимом19741975[`c_double`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_double)19761977.19781979#### `class ctypes.c_float`19801981Представляет тип данных C19821983`float`19841985. Конструктор принимает необязательный инициализатор с плавающей запятой.19861987#### `class ctypes.c_int`19881989Представляет тип данных C19901991`signed int`19921993. Конструктор принимает необязательный инициализатор целого типа; проверка переполнения не выполняется. На платформах, где19941995`sizeof(int) == sizeof(long)`19961997, он является псевдонимом19981999[`c_long`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_long)20002001.20022003#### `class ctypes.c_int8`20042005Представляет 8-битный тип данных C20062007`signed int`20082009. Обычно является псевдонимом20102011[`c_byte`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_byte)20122013.20142015#### `class ctypes.c_int16`20162017Представляет 16-битный тип данных C20182019`signed int`20202021. Обычно является псевдонимом20222023[`c_short`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_short)20242025.20262027#### `class ctypes.c_int32`20282029Представляет 32-битный тип данных C20302031`signed int`20322033. Обычно является псевдонимом20342035[`c_int`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_int)20362037.20382039#### `class ctypes.c_int64`20402041Представляет 64-битный тип данных C20422043`signed int`20442045. Обычно является псевдонимом20462047[`c_longlong`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_longlong)20482049.20502051#### `class ctypes.c_long`20522053Представляет тип данных C20542055`signed long`20562057. Конструктор принимает необязательный инициализатор целого типа; проверка переполнения не выполняется.20582059#### `class ctypes.c_longlong`20602061Представляет тип данных C20622063`signed long long`20642065. Конструктор принимает необязательный инициализатор целого типа; проверка переполнения не выполняется.20662067#### `class ctypes.c_short`20682069Представляет тип данных C20702071`signed short`20722073. Конструктор принимает необязательный инициализатор целого типа; проверка переполнения не выполняется.20742075#### `class ctypes.c_size_t`20762077Представляет тип данных C20782079`size_t`20802081.20822083#### `class ctypes.c_ubyte`20842085Представляет тип данных C20862087`unsigned char`20882089, интерпретирует значение как целое число небольшого размера. Конструктор принимает необязательный целочисленный инициализатор; проверка переполнения не выполняется.20902091#### `class ctypes.c_uint`20922093Представляет тип данных C20942095`unsigned int`20962097. Конструктор принимает необязательный целочисленный инициализатор; проверка переполнения не выполняется. На платформах, где20982099`sizeof(int) == sizeof(long)`21002101, это псевдоним для21022103[`c_ulong`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_ulong)21042105.21062107#### `class ctypes.c_uint8`21082109Представляет 8-битный тип данных C21102111`unsigned int`21122113. Обычно это псевдоним для21142115[`c_ubyte`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_ubyte)21162117.21182119#### `class ctypes.c_uint16`21202121Представляет 16-битный тип данных C21222123`unsigned int`21242125. Обычно это псевдоним для21262127[`c_ushort`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_ushort)21282129.21302131#### `class ctypes.c_uint32`21322133Представляет 32-битный тип данных C21342135`unsigned int`21362137. Обычно это псевдоним для21382139[`c_uint`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_uint)21402141.21422143#### `class ctypes.c_uint64`21442145Представляет 64-битный тип данных C21462147`unsigned int`21482149. Обычно это псевдоним для21502151[`c_ulonglong`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_ulonglong)21522153.21542155#### `class ctypes.c_ulong`21562157Представляет тип данных C21582159`unsigned long`21602161. Конструктор принимает необязательный целочисленный инициализатор; проверка переполнения не выполняется.21622163#### `class ctypes.c_ulonglong`21642165Представляет тип данных C21662167`unsigned long long`21682169. Конструктор принимает необязательный целочисленный инициализатор; проверка переполнения не выполняется.21702171#### `class ctypes.c_ushort`21722173Представляет тип данных C21742175`unsigned short`21762177. Конструктор принимает необязательный целочисленный инициализатор; проверка переполнения не выполняется.21782179#### `class ctypes.c_void_p`21802181Представляет тип C21822183`void *`21842185. Значение представляется как целое число. Конструктор принимает необязательный целочисленный инициализатор.21862187#### `class ctypes.c_wchar`21882189Представляет тип данных C21902191`wchar_t`21922193, интерпретирует значение как строку unicode из одного символа. Конструктор принимает необязательный строковый инициализатор; длина строки должна быть ровно один символ.21942195#### `class ctypes.c_wchar_p`21962197Представляет тип данных C21982199`wchar_t *`22002201, который должен быть указателем на завершающуюся нулём строку широких символов. Конструктор принимает целочисленный адрес или строку.22022203#### `class ctypes.c_bool`22042205Представляет тип данных C22062207`bool`22082209(точнее,22102211`_Bool`22122213из C99). Его значением может быть True или False, а конструктор принимает любой объект, имеющий логическое значение.22142215#### `class ctypes.HRESULT`22162217Только Windows: представляет значение22182219`HRESULT`22202221, содержащее информацию об успехе или ошибке вызова функции или метода.22222223#### `class ctypes.py_object`22242225Представляет тип данных C22262227[`PyObject *`](https://python-all.ru/3.1/c-api/structures.html#PyObject)22282229. Вызов без аргумента создаёт указатель22302231`NULL`22322233[`PyObject *`](https://python-all.ru/3.1/c-api/structures.html#PyObject)22342235.22362237Модуль `ctypes.wintypes` предоставляет ряд других специфичных для Windows типов данных, например `HWND`, `WPARAM` или `DWORD`. Также определены некоторые полезные структуры, такие как `MSG` или `RECT`.22382239### 15.15.2.8. Структурированные типы данных22402241#### `class ctypes.Union(*args, **kw)`22422243Абстрактный базовый класс для объединений в собственном порядке байт.22442245#### `class ctypes.BigEndianStructure(*args, **kw)`22462247Абстрактный базовый класс для структур в22482249*big endian*22502251порядке байтов.22522253#### `class ctypes.LittleEndianStructure(*args, **kw)`22542255Абстрактный базовый класс для структур в22562257*little endian*22582259порядке байтов.22602261Структуры с нестандартным порядком байтов не могут содержать поля типа указателя или любые другие типы данных, содержащие поля типа указателя.22622263#### `class ctypes.Structure(*args, **kw)`22642265Абстрактный базовый класс для структур в *нативном* порядке байтов.22662267Конкретные типы структур и объединений должны создаваться путем наследования от одного из этих типов и как минимум определять переменную класса [`_fields_`](https://python-all.ru/3.1/library/ctypes.html#ctypes.Structure._fields_). `ctypes` создаст [*дескрипторы*](https://python-all.ru/3.1/glossary.html#term-descriptor), которые позволяют читать и записывать поля через прямой доступ к атрибутам. Это22682269#### `_fields_`22702271Последовательность, определяющая поля структуры. Элементы должны быть 2-кортежами или 3-кортежами. Первый элемент – имя поля, второй элемент задает тип поля; это может быть любой тип данных ctypes.22722273Для полей целочисленных типов, таких как [`c_int`](https://python-all.ru/3.1/library/ctypes.html#ctypes.c_int), может быть указан третий необязательный элемент. Он должен быть небольшим положительным целым числом, определяющим разрядность поля.22742275Имена полей должны быть уникальными в пределах одной структуры или объединения. Это не проверяется, но при повторении имен доступно только одно поле.22762277Переменную класса [`_fields_`](https://python-all.ru/3.1/library/ctypes.html#ctypes.Structure._fields_) можно определить *после* оператора class, который определяет подкласс Structure; это позволяет создавать типы данных, которые прямо или косвенно ссылаются сами на себя:22782279```python2280class List(Structure):2281    pass2282List._fields_ = [("pnext", POINTER(List)),2283                 ...2284                ]2285```22862287Однако переменная класса [`_fields_`](https://python-all.ru/3.1/library/ctypes.html#ctypes.Structure._fields_) должна быть определена до первого использования типа (создания экземпляра, вызова [`sizeof()`](https://python-all.ru/3.1/library/ctypes.html#ctypes.sizeof) для него и т.д.). Последующие присваивания переменной класса [`_fields_`](https://python-all.ru/3.1/library/ctypes.html#ctypes.Structure._fields_) вызовут AttributeError.22882289Конструкторы подклассов Structure и Union принимают как позиционные, так и именованные аргументы. Позиционные аргументы используются для инициализации полей в том же порядке, в котором они указаны в определении [`_fields_`](https://python-all.ru/3.1/library/ctypes.html#ctypes.Structure._fields_), а именованные аргументы используются для инициализации полей с соответствующим именем.22902291Можно определять подподклассы типов структур; они наследуют поля базового класса плюс поля из [`_fields_`](https://python-all.ru/3.1/library/ctypes.html#ctypes.Structure._fields_), определённые в подподклассе, если таковые имеются.22922293#### `_pack_`22942295Необязательное небольшое целое число, позволяющее переопределить выравнивание полей структуры в экземпляре.22962297[`_pack_`](https://python-all.ru/3.1/library/ctypes.html#ctypes.Structure._pack_)22982299должен быть уже определён, когда присваивается23002301[`_fields_`](https://python-all.ru/3.1/library/ctypes.html#ctypes.Structure._fields_)23022303, иначе это не будет иметь эффекта.23042305#### `_anonymous_`23062307Необязательная последовательность, перечисляющая имена безымянных (анонимных) полей. [`_anonymous_`](https://python-all.ru/3.1/library/ctypes.html#ctypes.Structure._anonymous_) должен быть уже определён, когда присваивается [`_fields_`](https://python-all.ru/3.1/library/ctypes.html#ctypes.Structure._fields_), иначе это не будет иметь эффекта.23082309Поля, перечисленные в этой переменной, должны быть полями типа структуры или объединения. `ctypes` создаст дескрипторы в типе структуры, которые позволяют напрямую обращаться к вложенным полям без необходимости создавать поле структуры или объединения.23102311Вот пример типа (Windows):23122313```python2314class _U(Union):2315    _fields_ = [("lptdesc", POINTER(TYPEDESC)),2316                ("lpadesc", POINTER(ARRAYDESC)),2317                ("hreftype", HREFTYPE)]23182319class TYPEDESC(Structure):2320    _anonymous_ = ("u",)2321    _fields_ = [("u", _U),2322                ("vt", VARTYPE)]2323```23242325Структура `TYPEDESC` описывает тип данных COM; поле `vt` определяет, какое из полей объединения является действительным. Поскольку поле `u` определено как анонимное, теперь можно обращаться к членам напрямую через экземпляр TYPEDESC. `td.lptdesc` и `td.u.lptdesc` эквивалентны, но первый вариант быстрее, так как не требует создания временного экземпляра объединения:23262327```python2328td = TYPEDESC()2329td.vt = VT_PTR2330td.lptdesc = POINTER(some_type)2331td.u.lptdesc = POINTER(some_type)2332```23332334Можно определять подподклассы структур; они наследуют поля базового класса. Если в определении подкласса есть отдельная переменная [`_fields_`](https://python-all.ru/3.1/library/ctypes.html#ctypes.Structure._fields_), то поля, указанные в ней, добавляются к полям базового класса.23352336Конструкторы структур и объединений принимают как позиционные, так и именованные аргументы. Позиционные аргументы используются для инициализации полей-членов в том же порядке, в котором они появляются в [`_fields_`](https://python-all.ru/3.1/library/ctypes.html#ctypes.Structure._fields_). Именованные аргументы в конструкторе интерпретируются как присваивания атрибутов, поэтому они инициализируют [`_fields_`](https://python-all.ru/3.1/library/ctypes.html#ctypes.Structure._fields_) с тем же именем или создают новые атрибуты для имён, отсутствующих в [`_fields_`](https://python-all.ru/3.1/library/ctypes.html#ctypes.Structure._fields_).23372338### 15.15.2.9. Массивы и указатели23392340Пока не написано – пожалуйста, обратитесь к разделам [*Pointers*](https://python-all.ru/3.1/library/ctypes.html#ctypes-pointers) и [*Arrays*](https://python-all.ru/3.1/library/ctypes.html#ctypes-arrays) в руководстве.2341