# `ctypes` — A foreign function library for Python

Source code: Lib/ctypes

`ctypes` is a foreign function library for Python. It provides C compatible data types, and allows calling functions in DLLs or shared libraries. It can be used to wrap these libraries in pure Python.

This is an optional module. If it is missing from your copy of CPython, look for documentation from your distributor (that is, whoever provided Python to you). If you are the distributor, see Requirements for optional modules.

## підручник ctypes

Примітка: зразки коду в цьому підручнику використовують `doctest`, щоб переконатися, що вони справді працюють. Оскільки деякі зразки коду поводяться по-різному в Linux, Windows або macOS, вони містять директиви doctest у коментарях.

Примітка. Деякі зразки коду посилаються на тип ctypes `c_int`. На платформах, де `sizeof(long) == sizeof(int)`, це псевдонім `c_long`. Отже, вас не повинно бентежити, якщо надруковано `c_long`, якщо ви очікуєте `c_int` — вони насправді одного типу.

### Завантаження бібліотек динамічних посилань

`ctypes` exports the cdll, and on Windows windll and oledll objects, for loading dynamic link libraries.

You load libraries by accessing them as attributes of these objects. cdll loads libraries which export functions using the standard `cdecl` calling convention, while windll libraries call functions using the `stdcall` calling convention. oledll also uses the `stdcall` calling convention, and assumes the functions return a Windows `HRESULT` error code. The error code is used to automatically raise an `OSError` exception when the function call fails.

Змінено в версії 3.3: Помилки Windows викликали `WindowsError`, який тепер є псевдонімом `OSError`.

Here are some examples for Windows. Note that `msvcrt` is the MS standard C library containing most standard C functions, and uses the `cdecl` calling convention:

    >>> from ctypes import *
    >>> print(windll.kernel32)
    <WinDLL 'kernel32', handle ... at ...>
    >>> print(cdll.msvcrt)
    <CDLL 'msvcrt', handle ... at ...>
    >>> libc = cdll.msvcrt
    >>>

Windows автоматично додає звичайний суфікс файлу `.dll`.

Примітка

Доступ до стандартної бібліотеки C через `cdll.msvcrt` використовуватиме застарілу версію бібліотеки, яка може бути несумісною з тією, що використовується Python. Якщо можливо, використовуйте власні функції Python або імпортуйте та використовуйте модуль `msvcrt`.

On Linux, it is required to specify the filename including the extension to load a library, so attribute access can not be used to load libraries. Either the `LoadLibrary()` method of the dll loaders should be used, or you should load the library by creating an instance of CDLL by calling the constructor:

    >>> cdll.LoadLibrary("libc.so.6")
    <CDLL 'libc.so.6', handle ... at ...>
    >>> libc = CDLL("libc.so.6")
    >>> libc
    <CDLL 'libc.so.6', handle ... at ...>
    >>>

### Доступ до функцій із завантажених dll

Доступ до функцій здійснюється як атрибути об’єктів dll:

    >>> libc.printf
    <_FuncPtr object at 0x...>
    >>> print(windll.kernel32.GetModuleHandleA)
    <_FuncPtr object at 0x...>
    >>> print(windll.kernel32.MyOwnFunction)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "ctypes.py", line 239, in __getattr__
        func = _StdcallFuncPtr(name, self)
    AttributeError: function 'MyOwnFunction' not found
    >>>

Note that win32 system dlls like `kernel32` and `user32` often export ANSI as well as UNICODE versions of a function. The UNICODE version is exported with a `W` appended to the name, while the ANSI version is exported with an `A` appended to the name. The win32 `GetModuleHandle` function, which returns a module handle for a given module name, has the following C prototype, and a macro is used to expose one of them as `GetModuleHandle` depending on whether UNICODE is defined or not:

    /* ANSI version */
    HMODULE GetModuleHandleA(LPCSTR lpModuleName);
    /* UNICODE version */
    HMODULE GetModuleHandleW(LPCWSTR lpModuleName);

windll не намагається вибрати одну з них магією, ви повинні отримати доступ до потрібної вам версії, явно вказавши `GetModuleHandleA` або `GetModuleHandleW`, а потім викликати його за допомогою байтів або рядкових об’єктів відповідно.

Іноді бібліотеки dll експортують функції з іменами, які не є дійсними ідентифікаторами Python, наприклад `"??2@YAPAXI@Z"`. У цьому випадку ви повинні використовувати `getattr()`, щоб отримати функцію:

    >>> getattr(cdll.msvcrt, "??2@YAPAXI@Z")
    <_FuncPtr object at 0x...>
    >>>

У Windows деякі бібліотеки DLL експортують функції не за назвою, а за порядковим номером. Доступ до цих функцій можна отримати, проіндексувавши об’єкт dll з порядковим номером:

    >>> cdll.kernel32[1]
    <_FuncPtr object at 0x...>
    >>> cdll.kernel32[0]
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "ctypes.py", line 310, in __getitem__
        func = _StdcallFuncPtr(name, self)
    AttributeError: function ordinal 0 not found
    >>>

### Функції виклику

You can call these functions like any other Python callable. This example uses the `rand()` function, which takes no arguments and returns a pseudo-random integer:

    >>> print(libc.rand())
    1804289383

On Windows, you can call the `GetModuleHandleA()` function, which returns a win32 module handle (passing `None` as single argument to call it with a `NULL` pointer):

    >>> print(hex(windll.kernel32.GetModuleHandleA(None)))
    0x1d000000
    >>>

`ValueError` виникає, коли ви викликаєте функцію `stdcall` за угодою про виклик `cdecl`, або навпаки:

    >>> cdll.kernel32.GetModuleHandleA(None)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: Procedure probably called with not enough arguments (4 bytes missing)
    >>>

    >>> windll.msvcrt.printf(b"spam")
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: Procedure probably called with too many arguments (4 bytes in excess)
    >>>

Щоб дізнатися правильну умову виклику, вам потрібно переглянути файл заголовка C або документацію для функції, яку ви хочете викликати.

On Windows, `ctypes` uses win32 structured exception handling to prevent crashes from general protection faults when functions are called with invalid argument values:

    >>> windll.kernel32.GetModuleHandleA(32)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    OSError: exception: access violation reading 0x00000020
    >>>

There are, however, enough ways to crash Python with `ctypes`, so you should be careful anyway. The `faulthandler` module can be helpful in debugging crashes (e.g. from segmentation faults produced by erroneous C library calls).

`None`, integers, bytes objects and (unicode) strings are the only native Python objects that can directly be used as parameters in these function calls. `None` is passed as a C `NULL` pointer, bytes objects and strings are passed as pointer to the memory block that contains their data (char* or wchar_t*). Python integers are passed as the platform’s default C int type, their value is masked to fit into the C type.

Before we move on calling functions with other parameter types, we have to learn more about `ctypes` data types.

### Основні типи даних

`ctypes` defines a number of primitive C compatible data types:

тип ctypes | тип С | Тип Python
--- | --- | ---
`c_bool` | _Bool | bool (1)
`c_char` | char | 1-символьний об’єкт байтів
`c_wchar` | `wchar_t` | 1-символьний рядок
`c_byte` | char | внутр
`c_ubyte` | unsigned char | внутр
`c_short` | short | внутр
`c_ushort` | unsigned short | внутр
`c_int` | int | внутр
`c_int8` | `int8_t` | внутр
`c_int16` | `int16_t` | внутр
`c_int32` | `int32_t` | внутр
`c_int64` | `int64_t` | внутр
`c_uint` | unsigned int | внутр
`c_uint8` | `uint8_t` | внутр
`c_uint16` | `uint16_t` | внутр
`c_uint32` | `uint32_t` | внутр
`c_uint64` | `uint64_t` | внутр
`c_long` | long | внутр
`c_ulong` | unsigned long | внутр
`c_longlong` | __int64 or long long | внутр
`c_ulonglong` | unsigned __int64 or unsigned long long | внутр
`c_size_t` | `size_t` | внутр
`c_ssize_t` | `ssize_t` or Py_ssize_t | внутр
`c_time_t` | `time_t` | внутр
`c_float` | float | плавати
`c_double` | double | плавати
`c_longdouble` | long double | плавати
`c_char_p` | char* (NUL terminated) | bytes або `None`
`c_wchar_p` | wchar_t* (NUL terminated) | рядок або `None`
`c_void_p` | void* | int або `None`

1. Конструктор приймає будь-який об’єкт зі значенням істинності.

Additionally, if IEC 60559 compatible complex arithmetic (Annex G) is supported in both C and `libffi`, the following complex types are available:

тип ctypes | тип С | Тип Python
--- | --- | ---
`c_float_complex` | float complex | complex
`c_double_complex` | double complex | complex
`c_longdouble_complex` | long double complex | complex

Усі ці типи можна створити, викликавши їх із необов’язковим ініціалізатором правильного типу та значення:

    >>> c_int()
    c_long(0)
    >>> c_wchar_p("Hello, World")
    c_wchar_p(140018365411392)
    >>> c_ushort(-3)
    c_ushort(65533)
    >>>

Оскільки ці типи є змінними, їх значення також можна змінити пізніше:

    >>> i = c_int(42)
    >>> print(i)
    c_long(42)
    >>> print(i.value)
    42
    >>> i.value = -99
    >>> print(i.value)
    -99
    >>>

Assigning a new value to instances of the pointer types `c_char_p`, `c_wchar_p`, and `c_void_p` changes the memory location they point to, not the contents of the memory block (of course not, because Python string objects are immutable):

    >>> s = "Hello, World"
    >>> c_s = c_wchar_p(s)
    >>> print(c_s)
    c_wchar_p(139966785747344)
    >>> print(c_s.value)
    Hello World
    >>> c_s.value = "Hi, there"
    >>> print(c_s)              # the memory location has changed
    c_wchar_p(139966783348904)
    >>> print(c_s.value)
    Hi, there
    >>> print(s)                # first object is unchanged
    Hello, World
    >>>

Однак ви повинні бути обережними, щоб не передавати їх функціям, які очікують покажчиків на змінну пам’ять. Якщо вам потрібні змінні блоки пам’яті, ctypes має функцію `create_string_buffer()`, яка створює їх різними способами. Доступ до поточного вмісту блоку пам’яті можна отримати (або змінити) за допомогою властивості `raw`; якщо ви бажаєте отримати до нього доступ як до рядка з закінченням NUL, використовуйте властивість `value`:

    >>> from ctypes import *
    >>> p = create_string_buffer(3)            # create a 3 byte buffer, initialized to NUL bytes
    >>> print(sizeof(p), repr(p.raw))
    3 b'\x00\x00\x00'
    >>> p = create_string_buffer(b"Hello")     # create a buffer containing a NUL terminated string
    >>> print(sizeof(p), repr(p.raw))
    6 b'Hello\x00'
    >>> print(repr(p.value))
    b'Hello'
    >>> p = create_string_buffer(b"Hello", 10) # create a 10 byte buffer
    >>> print(sizeof(p), repr(p.raw))
    10 b'Hello\x00\x00\x00\x00\x00'
    >>> p.value = b"Hi"
    >>> print(sizeof(p), repr(p.raw))
    10 b'Hi\x00lo\x00\x00\x00\x00\x00'
    >>>

The `create_string_buffer()` function replaces the old `c_buffer()` function (which is still available as an alias). To create a mutable memory block containing unicode characters of the C type `wchar_t`, use the `create_unicode_buffer()` function.

### Функції виклику, продовження

Зауважте, що printf друкує на справжній стандартний канал виводу, а не на `sys.stdout`, тому ці приклади працюватимуть лише у підказці консолі, а не з IDLE або PythonWin:

    >>> printf = libc.printf
    >>> printf(b"Hello, %s\n", b"World!")
    Hello, World!
    14
    >>> printf(b"Hello, %S\n", "World!")
    Hello, World!
    14
    >>> printf(b"%d bottles of beer\n", 42)
    42 bottles of beer
    19
    >>> printf(b"%f bottles of beer\n", 42.5)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ctypes.ArgumentError: argument 2: TypeError: Don't know how to convert parameter 2
    >>>

As has been mentioned before, all Python types except integers, strings, and bytes objects have to be wrapped in their corresponding `ctypes` type, so that they can be converted to the required C data type:

    >>> printf(b"An int %d, a double %f\n", 1234, c_double(3.14))
    An int 1234, a double 3.140000
    31
    >>>

### Calling variadic functions

On a lot of platforms calling variadic functions through ctypes is exactly the same as calling functions with a fixed number of parameters. On some platforms, and in particular ARM64 for Apple Platforms, the calling convention for variadic functions is different than that for regular functions.

On those platforms it is required to specify the `argtypes` attribute for the regular, non-variadic, function arguments:

    libc.printf.argtypes = [ctypes.c_char_p]

Because specifying the attribute does not inhibit portability it is advised to always specify `argtypes` for all variadic functions.

### Виклик функцій із власними типами даних

You can also customize `ctypes` argument conversion to allow instances of your own classes be used as function arguments. `ctypes` looks for an `_as_parameter_` attribute and uses this as the function argument. The attribute must be an integer, string, bytes, a `ctypes` instance, or an object with an `_as_parameter_` attribute:

    >>> class Bottles:
    ...     def __init__(self, number):
    ...         self._as_parameter_ = number
    ...
    >>> bottles = Bottles(42)
    >>> printf(b"%d bottles of beer\n", bottles)
    42 bottles of beer
    19
    >>>

If you don’t want to store the instance’s data in the `_as_parameter_` instance variable, you could define a `property` which makes the attribute available on request.

### Вказівка необхідних типів аргументів (прототипів функцій)

It is possible to specify the required argument types of functions exported from DLLs by setting the `argtypes` attribute.

`argtypes` must be a sequence of C data types (the `printf()` function is probably not a good example here, because it takes a variable number and different types of parameters depending on the format string, on the other hand this is quite handy to experiment with this feature):

    >>> printf.argtypes = [c_char_p, c_char_p, c_int, c_double]
    >>> printf(b"String '%s', Int %d, Double %f\n", b"Hi", 10, 2.2)
    String 'Hi', Int 10, Double 2.200000
    37
    >>>

Зазначення формату захищає від несумісних типів аргументів (як прототип для функції C) і намагається перетворити аргументи на дійсні типи:

    >>> printf(b"%d %d %d", 1, 2, 3)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ctypes.ArgumentError: argument 2: TypeError: 'int' object cannot be interpreted as ctypes.c_char_p
    >>> printf(b"%s %d %f\n", b"X", 2, 3)
    X 2 3.000000
    13
    >>>

If you have defined your own classes which you pass to function calls, you have to implement a `from_param()` class method for them to be able to use them in the `argtypes` sequence. The `from_param()` class method receives the Python object passed to the function call, it should do a typecheck or whatever is needed to make sure this object is acceptable, and then return the object itself, its `_as_parameter_` attribute, or whatever you want to pass as the C function argument in this case. Again, the result should be an integer, string, bytes, a `ctypes` instance, or an object with an `_as_parameter_` attribute.

### Типи повернення

By default functions are assumed to return the C int type. Other return types can be specified by setting the `restype` attribute of the function object.

The C prototype of `time()` is `time_t time(time_t *)`. Because `time_t` might be of a different type than the default return type int, you should specify the `restype` attribute:

    >>> libc.time.restype = c_time_t

The argument types can be specified using `argtypes`:

    >>> libc.time.argtypes = (POINTER(c_time_t),)

To call the function with a `NULL` pointer as first argument, use `None`:

    >>> print(libc.time(None))
    1150640792

Here is a more advanced example, it uses the `strchr()` function, which expects a string pointer and a char, and returns a pointer to a string:

    >>> strchr = libc.strchr
    >>> strchr(b"abcdef", ord("d"))
    8059983
    >>> strchr.restype = c_char_p    # c_char_p is a pointer to a string
    >>> strchr(b"abcdef", ord("d"))
    b'def'
    >>> print(strchr(b"abcdef", ord("x")))
    None
    >>>

If you want to avoid the `ord("x")` calls above, you can set the `argtypes` attribute, and the second argument will be converted from a single character Python bytes object into a C char:

    >>> strchr.restype = c_char_p
    >>> strchr.argtypes = [c_char_p, c_char]
    >>> strchr(b"abcdef", b"d")
    b'def'
    >>> strchr(b"abcdef", b"def")
    Traceback (most recent call last):
    ctypes.ArgumentError: argument 2: TypeError: one character bytes, bytearray or integer expected
    >>> print(strchr(b"abcdef", b"x"))
    None
    >>> strchr(b"abcdef", b"d")
    b'def'
    >>>

You can also use a callable Python object (a function or a class for example) as the `restype` attribute, if the foreign function returns an integer. The callable will be called with the integer the C function returns, and the result of this call will be used as the result of your function call. This is useful to check for error return values and automatically raise an exception:

    >>> GetModuleHandle = windll.kernel32.GetModuleHandleA
    >>> def ValidHandle(value):
    ...     if value == 0:
    ...         raise WinError()
    ...     return value
    ...
    >>>
    >>> GetModuleHandle.restype = ValidHandle
    >>> GetModuleHandle(None)
    486539264
    >>> GetModuleHandle("something silly")
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 3, in ValidHandle
    OSError: [Errno 126] The specified module could not be found.
    >>>

`WinError` — це функція, яка викликає Windows `FormatMessage()` API, щоб отримати рядкове представлення коду помилки, і повертає виняткову ситуацію. `WinError` приймає додатковий параметр коду помилки, якщо ніхто не використовується, він викликає `GetLastError()`, щоб отримати його.

Please note that a much more powerful error checking mechanism is available through the `errcheck` attribute; see the reference manual for details.

### Передача покажчиків (або: передача параметрів за посиланням)

Іноді функція C API очікує вказівника на тип даних як параметр, ймовірно, для запису у відповідне розташування або якщо дані завеликі для передачі за значенням. Це також відомо як передача параметрів за посиланням.

`ctypes` exports the `byref()` function which is used to pass parameters by reference. The same effect can be achieved with the `pointer()` function, although `pointer()` does a lot more work since it constructs a real pointer object, so it is faster to use `byref()` if you don’t need the pointer object in Python itself:

    >>> i = c_int()
    >>> f = c_float()
    >>> s = create_string_buffer(b'\000' * 32)
    >>> print(i.value, f.value, repr(s.value))
    0 0.0 b''
    >>> libc.sscanf(b"1 3.14 Hello", b"%d %f %s",
    ...             byref(i), byref(f), s)
    3
    >>> print(i.value, f.value, repr(s.value))
    1 3.1400001049 b'Hello'
    >>>

### Структури та спілки

Structures and unions must derive from the `Structure` and `Union` base classes which are defined in the `ctypes` module. Each subclass must define a `_fields_` attribute. `_fields_` must be a list of 2-tuples, containing a field name and a field type.

The field type must be a `ctypes` type like `c_int`, or any other derived `ctypes` type: structure, union, array, pointer.

Ось простий приклад структури POINT, яка містить два цілі числа з іменами x і y, а також показує, як ініціалізувати структуру в конструкторі:

    >>> from ctypes import *
    >>> class POINT(Structure):
    ...     _fields_ = [("x", c_int),
    ...                 ("y", c_int)]
    ...
    >>> point = POINT(10, 20)
    >>> print(point.x, point.y)
    10 20
    >>> point = POINT(y=5)
    >>> print(point.x, point.y)
    0 5
    >>> POINT(1, 2, 3)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: too many initializers
    >>>

Однак можна будувати набагато складніші конструкції. Структура може сама містити інші структури, використовуючи структуру як тип поля.

Ось структура RECT, яка містить дві ТОЧКИ з іменами upperleft і lowerright:

    >>> class RECT(Structure):
    ...     _fields_ = [("upperleft", POINT),
    ...                 ("lowerright", POINT)]
    ...
    >>> rc = RECT(point)
    >>> print(rc.upperleft.x, rc.upperleft.y)
    0 5
    >>> print(rc.lowerright.x, rc.lowerright.y)
    0 0
    >>>

Вкладені структури також можна ініціалізувати в конструкторі кількома способами:

    >>> r = RECT(POINT(1, 2), POINT(3, 4))
    >>> r = RECT((1, 2), (3, 4))

Field descriptors can be retrieved from the class, they are useful for debugging because they can provide useful information. See `CField`:

    >>> POINT.x
    <ctypes.CField 'x' type=c_int, ofs=0, size=4>
    >>> POINT.y
    <ctypes.CField 'y' type=c_int, ofs=4, size=4>
    >>>

Попередження

`ctypes` does not support passing unions or structures with bit-fields to functions by value. While this may work on 32-bit x86, it’s not guaranteed by the library to work in the general case. Unions and structures with bit-fields should always be passed to functions by pointer.

### Structure/union layout, alignment and byte order

By default, Structure and Union fields are laid out in the same way the C compiler does it. It is possible to override this behavior entirely by specifying a `_layout_` class attribute in the subclass definition; see the attribute documentation for details.

It is possible to specify the maximum alignment for the fields and/or for the structure itself by setting the class attributes `_pack_` and/or `_align_`, respectively. See the attribute documentation for details.

`ctypes` uses the native byte order for Structures and Unions. To build structures with non-native byte order, you can use one of the `BigEndianStructure`, `LittleEndianStructure`, `BigEndianUnion`, and `LittleEndianUnion` base classes. These classes cannot contain pointer fields.

### Бітові поля в структурах і об’єднаннях

It is possible to create structures and unions containing bit fields. Bit fields are only possible for integer fields, the bit width is specified as the third item in the `_fields_` tuples:

    >>> class Int(Structure):
    ...     _fields_ = [("first_16", c_int, 16),
    ...                 ("second_16", c_int, 16)]
    ...
    >>> print(Int.first_16)
    <ctypes.CField 'first_16' type=c_int, ofs=0, bit_size=16, bit_offset=0>
    >>> print(Int.second_16)
    <ctypes.CField 'second_16' type=c_int, ofs=0, bit_size=16, bit_offset=16>

It is important to note that bit field allocation and layout in memory are not defined as a C standard; their implementation is compiler-specific. By default, Python will attempt to match the behavior of a «native» compiler for the current platform. See the `_layout_` attribute for details on the default behavior and how to change it.

### Масиви

Масиви - це послідовності, що містять фіксовану кількість екземплярів одного типу.

Рекомендований спосіб створення типів масивів – це множення типу даних на додатне ціле:

    TenPointsArrayType = POINT * 10

Ось приклад дещо штучного типу даних, структура, яка містить 4 ТОЧКИ серед іншого:

    >>> from ctypes import *
    >>> class POINT(Structure):
    ...     _fields_ = ("x", c_int), ("y", c_int)
    ...
    >>> class MyStruct(Structure):
    ...     _fields_ = [("a", c_int),
    ...                 ("b", c_float),
    ...                 ("point_array", POINT * 4)]
    >>>
    >>> print(len(MyStruct().point_array))
    4
    >>>

Екземпляри створюються звичайним способом за допомогою виклику класу:

    arr = TenPointsArrayType()
    for pt in arr:
        print(pt.x, pt.y)

Наведений вище код друкує серію рядків `0 0`, оскільки вміст масиву ініціалізовано нулями.

Також можна вказати ініціалізатори правильного типу:

    >>> from ctypes import *
    >>> TenIntegers = c_int * 10
    >>> ii = TenIntegers(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    >>> print(ii)
    <c_long_Array_10 object at 0x...>
    >>> for i in ii: print(i, end=" ")
    ...
    1 2 3 4 5 6 7 8 9 10
    >>>

### Покажчики

Pointer instances are created by calling the `pointer()` function on a `ctypes` type:

    >>> from ctypes import *
    >>> i = c_int(42)
    >>> pi = pointer(i)
    >>>

Екземпляри вказівника мають атрибут `contents`, який повертає об’єкт, на який вказує вказівник, об’єкт `i` вище:

    >>> pi.contents
    c_long(42)
    >>>

Note that `ctypes` does not have OOR (original object return), it constructs a new, equivalent object each time you retrieve an attribute:

    >>> pi.contents is i
    False
    >>> pi.contents is pi.contents
    False
    >>>

Призначення іншого екземпляра `c_int` атрибуту contents вказівника призведе до того, що вказівник вказуватиме на місце пам’яті, де це зберігається:

    >>> i = c_int(99)
    >>> pi.contents = i
    >>> pi.contents
    c_long(99)
    >>>

Екземпляри вказівників також можна індексувати цілими числами:

    >>> pi[0]
    99
    >>>

Присвоєння цілочисельному індексу змінює вказане значення:

    >>> print(i)
    c_long(99)
    >>> pi[0] = 22
    >>> print(i)
    c_long(22)
    >>>

Також можна використовувати індекси, відмінні від 0, але ви повинні знати, що ви робите, так само як у C: ви можете отримати доступ або змінити довільні місця пам’яті. Зазвичай ви використовуєте цю функцію, лише якщо отримуєте вказівник від функції C і знаєте, що вказівник насправді вказує на масив, а не на один елемент.

Behind the scenes, the `pointer()` function does more than simply create pointer instances, it has to create pointer types first. This is done with the `POINTER()` function, which accepts any `ctypes` type, and returns a new type:

    >>> PI = POINTER(c_int)
    >>> PI
    <class 'ctypes.LP_c_long'>
    >>> PI(42)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: expected c_long instead of int
    >>> PI(c_int(42))
    <ctypes.LP_c_long object at 0x...>
    >>>

Виклик типу покажчика без аргументу створює покажчик `NULL`. Покажчики `NULL` мають логічне значення `False`:

    >>> null_ptr = POINTER(c_int)()
    >>> print(bool(null_ptr))
    False
    >>>

`ctypes` checks for `NULL` when dereferencing pointers (but dereferencing invalid non-`NULL` pointers would crash Python):

    >>> null_ptr[0]
    Traceback (most recent call last):
        ....
    ValueError: NULL pointer access
    >>>

    >>> null_ptr[0] = 1234
    Traceback (most recent call last):
        ....
    ValueError: NULL pointer access
    >>>

### Thread safety without the GIL

From Python 3.13 onward, the GIL can be disabled on the free-threaded build. In ctypes, reads and writes to a single object concurrently is safe, but not across multiple objects:

>     >>> number = c_int(42)
>     >>> pointer_a = pointer(number)
>     >>> pointer_b = pointer(number)

In the above, it’s only safe for one object to read and write to the address at once if the GIL is disabled. So, `pointer_a` can be shared and written to across multiple threads, but only if `pointer_b` is not also attempting to do the same. If this is an issue, consider using a `threading.Lock` to synchronize access to memory:

>     >>> import threading
>     >>> lock = threading.Lock()
>     >>> # Thread 1
>     >>> with lock:
>     ...    pointer_a.contents = 24
>     >>> # Thread 2
>     >>> with lock:
>     ...    pointer_b.contents = 42

### Перетворення типів

Usually, ctypes does strict type checking. This means, if you have `POINTER(c_int)` in the `argtypes` list of a function or as the type of a member field in a structure definition, only instances of exactly the same type are accepted. There are some exceptions to this rule, where ctypes accepts other objects. For example, you can pass compatible array instances instead of pointer types. So, for `POINTER(c_int)`, ctypes accepts an array of c_int:

    >>> class Bar(Structure):
    ...     _fields_ = [("count", c_int), ("values", POINTER(c_int))]
    ...
    >>> bar = Bar()
    >>> bar.values = (c_int * 3)(1, 2, 3)
    >>> bar.count = 3
    >>> for i in range(bar.count):
    ...     print(bar.values[i])
    ...
    1
    2
    3
    >>>

In addition, if a function argument is explicitly declared to be a pointer type (such as `POINTER(c_int)`) in `argtypes`, an object of the pointed type (`c_int` in this case) can be passed to the function. ctypes will apply the required `byref()` conversion in this case automatically.

Щоб встановити для поля типу POINTER значення `NULL`, ви можете призначити `None`:

    >>> bar.values = None
    >>>

Sometimes you have instances of incompatible types. In C, you can cast one type into another type. `ctypes` provides a `cast()` function which can be used in the same way. The `Bar` structure defined above accepts `POINTER(c_int)` pointers or `c_int` arrays for its `values` field, but not instances of other types:

    >>> bar.values = (c_byte * 4)()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: incompatible types, c_byte_Array_4 instance instead of LP_c_long instance
    >>>

Для цих випадків зручна функція `cast()`.

Функцію `cast()` можна використати для приведення екземпляра ctypes до покажчика на інший тип даних ctypes. `cast()` приймає два параметри: об’єкт ctypes, який є чи може бути перетворений на певний вказівник, і тип вказівника ctypes. Він повертає екземпляр другого аргументу, який посилається на той самий блок пам’яті, що й перший аргумент:

    >>> a = (c_byte * 4)()
    >>> cast(a, POINTER(c_int))
    <ctypes.LP_c_long object at ...>
    >>>

Отже, `cast()` можна використовувати для призначення полю `values` `Bar` структури:

    >>> bar = Bar()
    >>> bar.values = cast((c_byte * 4)(), POINTER(c_int))
    >>> print(bar.values[0])
    0
    >>>

### Неповні типи

Неповні типи — це структури, об’єднання або масиви, члени яких ще не визначено. У C вони визначені прямими оголошеннями, які визначені пізніше:

    struct cell; /* forward declaration */

    struct cell {
        char *name;
        struct cell *next;
    };

Прямий переклад у код ctypes буде таким, але він не працює:

    >>> class cell(Structure):
    ...     _fields_ = [("name", c_char_p),
    ...                 ("next", POINTER(cell))]
    ...
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 2, in cell
    NameError: name 'cell' is not defined
    >>>

because the new `class cell` is not available in the class statement itself. In `ctypes`, we can define the `cell` class and set the `_fields_` attribute later, after the class statement:

    >>> from ctypes import *
    >>> class cell(Structure):
    ...     pass
    ...
    >>> cell._fields_ = [("name", c_char_p),
    ...                  ("next", POINTER(cell))]
    >>>

Давайте спробуємо. Ми створюємо два екземпляри `cell` і дозволяємо їм вказувати один на одного, і, нарешті, слідуємо за ланцюжком вказівників кілька разів:

    >>> c1 = cell()
    >>> c1.name = b"foo"
    >>> c2 = cell()
    >>> c2.name = b"bar"
    >>> c1.next = pointer(c2)
    >>> c2.next = pointer(c1)
    >>> p = c1
    >>> for i in range(8):
    ...     print(p.name, end=" ")
    ...     p = p.next[0]
    ...
    foo bar foo bar foo bar foo bar
    >>>

### Функції зворотного виклику

`ctypes` allows creating C callable function pointers from Python callables. These are sometimes called callback functions.

По-перше, ви повинні створити клас для функції зворотного виклику. Клас знає угоду про виклики, тип повернення, а також кількість і типи аргументів, які ця функція отримає.

Фабрична функція `CFUNCTYPE()` створює типи для функцій зворотного виклику за допомогою угоди про виклики `cdecl`. У Windows фабрична функція `WINFUNCTYPE()` створює типи для функцій зворотного виклику за допомогою угоди про виклики `stdcall`.

Обидві ці фабричні функції викликаються з типом результату як першим аргументом, а функції зворотного виклику – очікуваними типами аргументів як рештою аргументів.

I will present an example here which uses the standard C library’s `qsort()` function, that is used to sort items with the help of a callback function. `qsort()` will be used to sort an array of integers:

    >>> IntArray5 = c_int * 5
    >>> ia = IntArray5(5, 1, 7, 33, 99)
    >>> qsort = libc.qsort
    >>> qsort.restype = None
    >>>

`qsort()` must be called with a pointer to the data to sort, the number of items in the data array, the size of one item, and a pointer to the comparison function, the callback. The callback will then be called with two pointers to items, and it must return a negative integer if the first item is smaller than the second, a zero if they are equal, and a positive integer otherwise.

Таким чином, наша функція зворотного виклику отримує покажчики на цілі числа та повинна повертати ціле число. Спочатку ми створюємо `type` для функції зворотного виклику:

    >>> CMPFUNC = CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
    >>>

Щоб почати, ось простий зворотний виклик, який показує значення, які він отримує:

    >>> def py_cmp_func(a, b):
    ...     print("py_cmp_func", a[0], b[0])
    ...     return 0
    ...
    >>> cmp_func = CMPFUNC(py_cmp_func)
    >>>

Результат:

    >>> qsort(ia, len(ia), sizeof(c_int), cmp_func)
    py_cmp_func 5 1
    py_cmp_func 33 99
    py_cmp_func 7 33
    py_cmp_func 5 7
    py_cmp_func 1 7
    >>>

Тепер ми фактично можемо порівняти два елементи та повернути корисний результат:

    >>> def py_cmp_func(a, b):
    ...     print("py_cmp_func", a[0], b[0])
    ...     return a[0] - b[0]
    ...
    >>>
    >>> qsort(ia, len(ia), sizeof(c_int), CMPFUNC(py_cmp_func))
    py_cmp_func 5 1
    py_cmp_func 33 99
    py_cmp_func 7 33
    py_cmp_func 1 7
    py_cmp_func 5 7
    >>>

Як ми можемо легко перевірити, наш масив зараз відсортовано:

    >>> for i in ia: print(i, end=" ")
    ...
    1 5 7 33 99
    >>>

Фабрики функцій можна використовувати як фабрики декораторів, тому ми також можемо написати:

    >>> @CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
    ... def py_cmp_func(a, b):
    ...     print("py_cmp_func", a[0], b[0])
    ...     return a[0] - b[0]
    ...
    >>> qsort(ia, len(ia), sizeof(c_int), py_cmp_func)
    py_cmp_func 5 1
    py_cmp_func 33 99
    py_cmp_func 7 33
    py_cmp_func 1 7
    py_cmp_func 5 7
    >>>

Примітка

Make sure you keep references to `CFUNCTYPE()` objects as long as they are used from C code. `ctypes` doesn’t, and if you don’t, they may be garbage collected, crashing your program when a callback is made.

Також зауважте, що якщо функція зворотнього виклику викликається в потоці, створеному поза контролем Python (наприклад, зовнішнім кодом, який викликає зворотній виклик), ctypes створює новий фіктивний потік Python під час кожного виклику. Така поведінка є правильною для більшості цілей, але це означає, що значення, збережені в `threading.local` не збережуться в різних зворотних викликах, навіть якщо ці виклики здійснюються з того самого потоку C.

### Доступ до значень, експортованих із dll

Some shared libraries not only export functions, they also export variables. An example in the Python library itself is the `Py_Version`, Python runtime version number encoded in a single constant integer.

`ctypes` can access values like this with the `in_dll()` class methods of the type. pythonapi is a predefined symbol giving access to the Python C api:

    >>> version = ctypes.c_int.in_dll(ctypes.pythonapi, "Py_Version")
    >>> print(hex(version.value))
    0x30c00a0

Розширений приклад, який також демонструє використання покажчиків, звертається до покажчика `PyImport_FrozenModules`, експортованого Python.

Цитування документів для цього значення:

> This pointer is initialized to point to an array of `_frozen` records, terminated by one whose members are all `NULL` or zero. When a frozen module is imported, it is searched in this table. Third-party code could play tricks with this to provide a dynamically created collection of frozen modules.

So manipulating this pointer could even prove useful. To restrict the example size, we show only how this table can be read with `ctypes`:

    >>> from ctypes import *
    >>>
    >>> class struct_frozen(Structure):
    ...     _fields_ = [("name", c_char_p),
    ...                 ("code", POINTER(c_ubyte)),
    ...                 ("size", c_int),
    ...                 ("get_code", POINTER(c_ubyte)),  # Function pointer
    ...                ]
    ...
    >>>

We have defined the `_frozen` data type, so we can get the pointer to the table:

    >>> FrozenTable = POINTER(struct_frozen)
    >>> table = FrozenTable.in_dll(pythonapi, "_PyImport_FrozenBootstrap")
    >>>

Оскільки `table` є `покажчиком` на масив `struct_frozen` записів, ми можемо перебирати його, але нам просто потрібно переконатися, що наш цикл завершується, оскільки покажчики не мають розміру. Рано чи пізно він, ймовірно, вийде з ладу через порушення прав доступу чи щось інше, тому краще вийти з циклу, коли ми натиснемо запис `NULL`:

    >>> for item in table:
    ...     if item.name is None:
    ...         break
    ...     print(item.name.decode("ascii"), item.size)
    ...
    _frozen_importlib 31764
    _frozen_importlib_external 41499
    zipimport 12345
    >>>

Той факт, що стандартний Python має заморожений модуль і заморожений пакет (позначений від’ємним елементом `size`), невідомий, він використовується лише для тестування. Спробуйте, наприклад, `import __hello__`.

### Сюрпризи

There are some edges in `ctypes` where you might expect something other than what actually happens.

Розглянемо такий приклад:

    >>> from ctypes import *
    >>> class POINT(Structure):
    ...     _fields_ = ("x", c_int), ("y", c_int)
    ...
    >>> class RECT(Structure):
    ...     _fields_ = ("a", POINT), ("b", POINT)
    ...
    >>> p1 = POINT(1, 2)
    >>> p2 = POINT(3, 4)
    >>> rc = RECT(p1, p2)
    >>> print(rc.a.x, rc.a.y, rc.b.x, rc.b.y)
    1 2 3 4
    >>> # now swap the two points
    >>> rc.a, rc.b = rc.b, rc.a
    >>> print(rc.a.x, rc.a.y, rc.b.x, rc.b.y)
    3 4 3 4
    >>>

Хм Ми, безумовно, очікували, що останній оператор виведе `3 4 1 2`. Що трапилось? Ось кроки рядка `rc.a, rc.b = rc.b, rc.a`:

    >>> temp0, temp1 = rc.b, rc.a
    >>> rc.a = temp0
    >>> rc.b = temp1
    >>>

Зауважте, що `temp0` і `temp1` є об’єктами, які все ще використовують внутрішній буфер об’єкта `rc` вище. Отже, виконання `rc.a = temp0` копіює вміст буфера `temp0` у буфер `rc`. Це, у свою чергу, змінює вміст `temp1`. Отже, останнє призначення `rc.b = temp1` не має очікуваного ефекту.

Майте на увазі, що отримання підоб’єктів зі структур, об’єднань і масивів не копіює підоб’єкт, натомість отримує обгортку об’єкта, який отримує доступ до основного буфера кореневого об’єкта.

Інший приклад, який може поводитися інакше, ніж очікувалося, це:

    >>> s = c_char_p()
    >>> s.value = b"abc def ghi"
    >>> s.value
    b'abc def ghi'
    >>> s.value is s.value
    False
    >>>

Примітка

Об’єкти, створені з `c_char_p`, можуть мати значення лише байтів або цілих чисел.

Чому він друкує `False`? Екземпляри ctypes — це об’єкти, що містять блок пам’яті плюс деякі descriptor, що мають доступ до вмісту пам’яті. Зберігання об’єкта Python у блоці пам’яті не зберігає сам об’єкт, натомість зберігається `вміст` об’єкта. Повторний доступ до вмісту щоразу створює новий об’єкт Python!

### Типи даних змінного розміру

`ctypes` provides some support for variable-sized arrays and structures.

Функцію `resize()` можна використовувати для зміни розміру буфера пам’яті існуючого об’єкта ctypes. Функція приймає об’єкт як перший аргумент, а запитуваний розмір у байтах як другий аргумент. Блок пам’яті не може бути меншим, ніж природний блок пам’яті, визначений типом об’єкта, `ValueError` виникає, якщо це спробувати:

    >>> short_array = (c_short * 4)()
    >>> print(sizeof(short_array))
    8
    >>> resize(short_array, 4)
    Traceback (most recent call last):
        ...
    ValueError: minimum size is 8
    >>> resize(short_array, 32)
    >>> sizeof(short_array)
    32
    >>> sizeof(type(short_array))
    8
    >>>

Це гарно і добре, але як отримати доступ до додаткових елементів, що містяться в цьому масиві? Оскільки тип все ще знає лише про 4 елементи, ми отримуємо помилки під час доступу до інших елементів:

    >>> short_array[:]
    [0, 0, 0, 0]
    >>> short_array[7]
    Traceback (most recent call last):
        ...
    IndexError: invalid index
    >>>

Another way to use variable-sized data types with `ctypes` is to use the dynamic nature of Python, and (re-)define the data type after the required size is already known, on a case by case basis.

## посилання на ctypes

### Пошук спільних бібліотек

Під час програмування скомпільованою мовою доступ до спільних бібліотек здійснюється під час компіляції/зв’язування програми та під час виконання програми.

The purpose of the `find_library()` function is to locate a library in a way similar to what the compiler or runtime loader does (on platforms with several versions of a shared library the most recent should be loaded), while the ctypes library loaders act like when a program is run, and call the runtime loader directly.

The `ctypes.util` module provides a function which can help to determine the library to load.

ctypes.util.find_library(name)

  Спробуйте знайти бібліотеку та повернути шлях. name — це назва бібліотеки без будь-якого префікса, як-от lib, суфікса, як-от `.so`, `.dylib` або номера версії (це форма, яка використовується для параметра компонування posix `- l`). Якщо бібліотеки не знайдено, повертає `None`.

Точна функція залежить від системи.

On Linux, `find_library()` tries to run external programs (`/sbin/ldconfig`, `gcc`, `objdump` and `ld`) to find the library file. It returns the filename of the library file.

Note that if the output of these programs does not correspond to the dynamic linker used by Python, the result of this function may be misleading.

Змінено в версії 3.6: У Linux значення змінної середовища `LD_LIBRARY_PATH` використовується під час пошуку бібліотек, якщо бібліотеку неможливо знайти будь-яким іншим способом.

Ось кілька прикладів:

    >>> from ctypes.util import find_library
    >>> find_library("m")
    'libm.so.6'
    >>> find_library("c")
    'libc.so.6'
    >>> find_library("bz2")
    'libbz2.so.1.0'
    >>>

On macOS and Android, `find_library()` uses the system’s standard naming schemes and paths to locate the library, and returns a full pathname if successful:

    >>> from ctypes.util import find_library
    >>> find_library("c")
    '/usr/lib/libc.dylib'
    >>> find_library("m")
    '/usr/lib/libm.dylib'
    >>> find_library("bz2")
    '/usr/lib/libbz2.dylib'
    >>> find_library("AGL")
    '/System/Library/Frameworks/AGL.framework/AGL'
    >>>

On Windows, `find_library()` searches along the system search path, and returns the full pathname, but since there is no predefined naming scheme a call like `find_library("c")` will fail and return `None`.

If wrapping a shared library with `ctypes`, it may be better to determine the shared library name at development time, and hardcode that into the wrapper module instead of using `find_library()` to locate the library at runtime.

### Listing loaded shared libraries

When writing code that relies on code loaded from shared libraries, it can be useful to know which shared libraries have already been loaded into the current process.

The `ctypes.util` module provides the `dllist()` function, which calls the different APIs provided by the various platforms to help determine which shared libraries have already been loaded into the current process.

The exact output of this function will be system dependent. On most platforms, the first entry of this list represents the current process itself, which may be an empty string. For example, on glibc-based Linux, the return may look like:

    >>> from ctypes.util import dllist
    >>> dllist()
    ['', 'linux-vdso.so.1', '/lib/x86_64-linux-gnu/libm.so.6', '/lib/x86_64-linux-gnu/libc.so.6', ... ]

### Завантаження спільних бібліотек

Є кілька способів завантажити спільні бібліотеки в процес Python. Одним із способів є створення екземпляра одного з наступних класів:

class ctypes.CDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None)

  Instances of this class represent loaded shared libraries. Functions in these libraries use the standard C calling convention, and are assumed to return int.

  У Windows створення екземпляра `CDLL` може завершитися помилкою, навіть якщо ім’я DLL існує. Якщо залежну DLL від завантаженої DLL не знайдено, виникає помилка `OSError` із повідомленням «[WinError 126] Не вдалося знайти вказаний модуль». Це повідомлення про помилку не містить назви відсутня DLL, оскільки Windows API не повертає цю інформацію, що ускладнює діагностику цієї помилки. Щоб усунути цю помилку та визначити, яку DLL не знайдено, потрібно знайти список залежних DLL і визначити, яка з них не знайдена, за допомогою засобів налагодження та трасування Windows.

  Змінено в версії 3.12: The name parameter can now be a path-like object.

Дивись також

Інструмент Microsoft DUMPBIN – Інструмент для пошуку залежних DLL.

class ctypes.OleDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None)

  Instances of this class represent loaded shared libraries, functions in these libraries use the `stdcall` calling convention, and are assumed to return the windows specific `HRESULT` code. `HRESULT` values contain information specifying whether the function call failed or succeeded, together with additional error code. If the return value signals a failure, an `OSError` is automatically raised.

  Availability: Windows

  Змінено в версії 3.3: `WindowsError` used to be raised, which is now an alias of `OSError`.

  Змінено в версії 3.12: The name parameter can now be a path-like object.

class ctypes.WinDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None)

  Instances of this class represent loaded shared libraries, functions in these libraries use the `stdcall` calling convention, and are assumed to return int by default.

  Availability: Windows

  Змінено в версії 3.12: The name parameter can now be a path-like object.

global interpreter lock Python знімається перед викликом будь-якої функції, експортованої цими бібліотеками, і знову отримується після цього.

class ctypes.PyDLL(name, mode=DEFAULT_MODE, handle=None)

  Екземпляри цього класу поводяться як екземпляри `CDLL`, за винятком того, що GIL Python не звільняється під час виклику функції, а після виконання функції перевіряється позначка помилки Python. Якщо встановлено позначку помилки, виникає виняток Python.

  Таким чином, це корисно лише для прямого виклику API-функцій Python C.

  Змінено в версії 3.12: The name parameter can now be a path-like object.

All these classes can be instantiated by calling them with at least one argument, the pathname of the shared library. If you have an existing handle to an already loaded shared library, it can be passed as the `handle` named parameter, otherwise the underlying platform’s `dlopen()` or `LoadLibrary()` function is used to load the library into the process, and to get a handle to it.

Параметр mode можна використовувати для визначення способу завантаження бібліотеки. Додаткову інформацію див. на сторінці довідки dlopen(3). У Windows режим ігнорується. У системах posix RTLD_NOW завжди додається та не налаштовується.

The use_errno parameter, when set to true, enables a ctypes mechanism that allows accessing the system `errno` error number in a safe way. `ctypes` maintains a thread-local copy of the system’s `errno` variable; if you call foreign functions created with `use_errno=True` then the `errno` value before the function call is swapped with the ctypes private copy, the same happens immediately after the function call.

Функція `ctypes.get_errno()` повертає значення приватної копії ctypes, а функція `ctypes.set_errno()` змінює приватну копію ctypes на нове значення та повертає попереднє значення.

The use_last_error parameter, when set to true, enables the same mechanism for the Windows error code which is managed by the `GetLastError()` and `SetLastError()` Windows API functions; `ctypes.get_last_error()` and `ctypes.set_last_error()` are used to request and change the ctypes private copy of the windows error code.

The winmode parameter is used on Windows to specify how the library is loaded (since mode is ignored). It takes any value that is valid for the Win32 API `LoadLibraryEx` flags parameter. When omitted, the default is to use the flags that result in the most secure DLL load, which avoids issues such as DLL hijacking. Passing the full path to the DLL is the safest way to ensure the correct library and dependencies are loaded.

Змінено в версії 3.8: Додано параметр winmode.

ctypes.RTLD_GLOBAL

  Прапор для використання як параметр mode. На платформах, де цей прапорець недоступний, він визначається як цілий нуль.

ctypes.RTLD_LOCAL

  Прапор для використання як параметр mode. На платформах, де це недоступно, це те саме, що RTLD_GLOBAL.

ctypes.DEFAULT_MODE

  Типовий режим, який використовується для завантаження спільних бібліотек. В OSX 10.3 це RTLD_GLOBAL, інакше це те саме, що RTLD_LOCAL.

Екземпляри цих класів не мають відкритих методів. Доступ до функцій, експортованих спільною бібліотекою, можна отримати як за атрибутами або за індексом. Будь ласка, зверніть увагу, що доступ до функції через атрибут кешує результат, тому повторний доступ повертає той самий об’єкт щоразу. З іншого боку, доступ до нього через індекс кожного разу повертає новий об’єкт:

    >>> from ctypes import CDLL
    >>> libc = CDLL("libc.so.6")  # On Linux
    >>> libc.time == libc.time
    True
    >>> libc['time'] == libc['time']
    False

Доступні такі загальнодоступні атрибути, їх імена починаються з підкреслення, щоб не суперечити ім’ям експортованих функцій:

PyDLL._handle

  Системний дескриптор, який використовується для доступу до бібліотеки.

PyDLL._name

  Ім’я бібліотеки, передане в конструктор.

Shared libraries can also be loaded by using one of the prefabricated objects, which are instances of the `LibraryLoader` class, either by calling the `LoadLibrary()` method, or by retrieving the library as attribute of the loader instance.

class ctypes.LibraryLoader(dlltype)

  Клас, який завантажує спільні бібліотеки. dlltype має бути одним із типів `CDLL`, `PyDLL`, `WinDLL` або `OleDLL`.

  `__getattr__()` has special behavior: It allows loading a shared library by accessing it as attribute of a library loader instance. The result is cached, so repeated attribute accesses return the same library each time.

  LoadLibrary(name)

    Завантажте спільну бібліотеку в процес і поверніть її. Цей метод завжди повертає новий екземпляр бібліотеки.

Ці збірні бібліотечні завантажувачі доступні:

ctypes.cdll

  Створює екземпляри `CDLL`.

ctypes.windll

  Creates `WinDLL` instances.

  Availability: Windows

ctypes.oledll

  Creates `OleDLL` instances.

  Availability: Windows

ctypes.pydll

  Створює екземпляри `PyDLL`.

Для прямого доступу до API C Python доступний готовий до використання об’єкт спільної бібліотеки Python:

ctypes.pythonapi

  An instance of `PyDLL` that exposes Python C API functions as attributes. Note that all these functions are assumed to return C int, which is of course not always the truth, so you have to assign the correct `restype` attribute to use these functions.

Завантаження бібліотеки через будь-який із цих об’єктів викликає подію аудиту `ctypes.dlopen` з рядковим аргументом `name`, іменем, яке використовується для завантаження бібліотеки.

Доступ до функції у завантаженій бібліотеці викликає подію аудиту `ctypes.dlsym` з аргументами `library` (об’єкт бібліотеки) і `name` (ім’я символу у вигляді рядка або цілого числа).

У випадках, коли доступний лише дескриптор бібліотеки, а не об’єкт, доступ до функції викликає подію аудиту `ctypes.dlsym/handle` з аргументами `handle` (необроблений дескриптор бібліотеки) і `name`.

### Іноземні функції

As explained in the previous section, foreign functions can be accessed as attributes of loaded shared libraries. The function objects created in this way by default accept any number of arguments, accept any ctypes data instances as arguments, and return the default result type specified by the library loader.

They are instances of a private local class `_FuncPtr` (not exposed in `ctypes`) which inherits from the private `_CFuncPtr` class:

    >>> import ctypes
    >>> lib = ctypes.CDLL(None)
    >>> issubclass(lib._FuncPtr, ctypes._CFuncPtr)
    True
    >>> lib._FuncPtr is ctypes._CFuncPtr
    False

class ctypes._CFuncPtr

  Базовий клас для зовнішніх функцій C, що викликаються.

  Примірники сторонніх функцій також є C-сумісними типами даних; вони представляють покажчики функцій C.

  Цю поведінку можна налаштувати шляхом призначення спеціальних атрибутів стороннього функціонального об’єкта.

  restype

    Assign a ctypes type to specify the result type of the foreign function. Use `None` for void, a function not returning anything.

    It is possible to assign a callable Python object that is not a ctypes type, in this case the function is assumed to return a C int, and the callable will be called with this integer, allowing further processing or error checking. Using this is deprecated, for more flexible post processing or error checking use a ctypes data type as `restype` and assign a callable to the `errcheck` attribute.

  argtypes

    Призначте кортеж типів ctypes, щоб указати типи аргументів, які приймає функція. Функції, які використовують угоду про виклики `stdcall`, можуть бути викликані лише з тією ж кількістю аргументів, що й довжина цього кортежу; функції, що використовують угоду про виклики C, також приймають додаткові, невизначені аргументи.

    When a foreign function is called, each actual argument is passed to the `from_param()` class method of the items in the `argtypes` tuple, this method allows adapting the actual argument to an object that the foreign function accepts. For example, a `c_char_p` item in the `argtypes` tuple will convert a string passed as argument into a bytes object using ctypes conversion rules.

    New: It is now possible to put items in argtypes which are not ctypes types, but each item must have a `from_param()` method which returns a value usable as argument (integer, string, ctypes instance). This allows defining adapters that can adapt custom objects as function parameters.

  errcheck

    Призначте цьому атрибуту функцію Python або інший виклик. Викликається з трьома або більше аргументами:

    callable(result, func, arguments)

      result is what the foreign function returns, as specified by the `restype` attribute.

      func — це сам зовнішній об’єкт функції, це дозволяє повторно використовувати той самий об’єкт, що викликається, для перевірки або постобробки результатів кількох функцій.

      Аргументи — це кортеж, що містить параметри, спочатку передані до виклику функції, що дозволяє спеціалізувати поведінку на використовуваних аргументах.

    Об’єкт, який повертає ця функція, буде повернено з виклику зовнішньої функції, але він також може перевірити значення результату та викликати виняток, якщо виклик зовнішньої функції не вдався.

On Windows, when a foreign function call raises a system exception (for example, due to an access violation), it will be captured and replaced with a suitable Python exception. Further, an auditing event `ctypes.set_exception` with argument `code` will be raised, allowing an audit hook to replace the exception with its own.

Some ways to invoke foreign function calls as well as some of the functions in this module may raise an auditing event `ctypes.call_function` with arguments `function pointer` and `arguments`.

### Прототипи функцій

Сторонні функції також можуть бути створені шляхом інстанціювання прототипів функцій. Прототипи функцій подібні до прототипів функцій у C; вони описують функцію (тип повернення, типи аргументів, угоду про виклики) без визначення реалізації. Фабричні функції мають викликатися з потрібним типом результату та типами аргументів функції, і їх можна використовувати як фабрики декораторів, і як такі застосовувати до функцій за допомогою синтаксису `@wrapper`. Перегляньте Функції зворотного виклику для прикладів.

ctypes.CFUNCTYPE(restype, *argtypes, use_errno=False, use_last_error=False)

  Повернений прототип функції створює функції, які використовують стандартну угоду про виклик C. Функція звільнить GIL під час виклику. Якщо use_errno має значення true, приватна копія ctypes системної змінної `errno` обмінюється справжнім значенням `errno` до і після виклику; use_last_error робить те саме для коду помилки Windows.

ctypes.WINFUNCTYPE(restype, *argtypes, use_errno=False, use_last_error=False)

  The returned function prototype creates functions that use the `stdcall` calling convention. The function will release the GIL during the call. use_errno and use_last_error have the same meaning as above.

  Availability: Windows

ctypes.PYFUNCTYPE(restype, *argtypes)

  Повернений прототип функції створює функції, які використовують угоду про виклики Python. Функція не звільняє GIL під час виклику.

Прототипи функцій, створені цими фабричними функціями, можуть бути створені різними способами, залежно від типу та кількості параметрів у виклику:

prototype(address)

  Повертає зовнішню функцію за вказаною адресою, яка має бути цілим числом.

prototype(callable)

  Створіть функцію виклику C (функцію зворотного виклику) з Python callable.

prototype(func_spec[, paramflags])

  Повертає зовнішню функцію, експортовану спільною бібліотекою. func_spec має бути 2-кортежем `(name_or_ordinal, library)`. Перший елемент — це ім’я експортованої функції у вигляді рядка або порядковий номер експортованої функції у вигляді малого цілого числа. Другий елемент — екземпляр спільної бібліотеки.

prototype(vtbl_index, name[, paramflags[, iid]])

  Повертає зовнішню функцію, яка викликає метод COM. vtbl_index — це індекс у таблиці віртуальних функцій, мале невід’ємне ціле число. ім’я — це ім’я методу COM. iid — це додатковий покажчик на ідентифікатор інтерфейсу, який використовується в розширеному звіті про помилки.

  If iid is not specified, an `OSError` is raised if the COM method call fails. If iid is specified, a `COMError` is raised instead.

  COM methods use a special calling convention: They require a pointer to the COM interface as first argument, in addition to those parameters that are specified in the `argtypes` tuple.

  Availability: Windows

Необов’язковий параметр paramflags створює зовнішні обгортки функцій із набагато більшою функціональністю, ніж функції, описані вище.

paramflags must be a tuple of the same length as `argtypes`.

Кожен елемент у цьому кортежі містить додаткову інформацію про параметр, це має бути кортеж, що містить один, два або три елементи.

Перший елемент є цілим числом, що містить комбінацію прапорів напрямку для параметра:

> 1

>   Визначає вхідний параметр для функції.

> 2

>   Вихідний параметр. Стороння функція заповнює значення.

> 4

>   Вхідний параметр, який за умовчанням дорівнює нулю.

Другим необов’язковим елементом є назва параметра у вигляді рядка. Якщо це вказано, зовнішня функція може бути викликана з іменованими параметрами.

Додатковий третій елемент є значенням за замовчуванням для цього параметра.

The following example demonstrates how to wrap the Windows `MessageBoxW` function so that it supports default parameters and named arguments. The C declaration from the windows header file is this:

    WINUSERAPI int WINAPI
    MessageBoxW(
        HWND hWnd,
        LPCWSTR lpText,
        LPCWSTR lpCaption,
        UINT uType);

Here is the wrapping with `ctypes`:

    >>> from ctypes import c_int, WINFUNCTYPE, windll
    >>> from ctypes.wintypes import HWND, LPCWSTR, UINT
    >>> prototype = WINFUNCTYPE(c_int, HWND, LPCWSTR, LPCWSTR, UINT)
    >>> paramflags = (1, "hwnd", 0), (1, "text", "Hi"), (1, "caption", "Hello from ctypes"), (1, "flags", 0)
    >>> MessageBox = prototype(("MessageBoxW", windll.user32), paramflags)

Сторонню функцію `MessageBox` тепер можна викликати такими способами:

    >>> MessageBox()
    >>> MessageBox(text="Spam, spam, spam")
    >>> MessageBox(flags=2, text="foo bar")

Другий приклад демонструє вихідні параметри. Функція `GetWindowRect` win32 отримує розміри вказаного вікна шляхом копіювання їх у структуру `RECT`, яку має надати абонент. Ось оголошення C:

    WINUSERAPI BOOL WINAPI
    GetWindowRect(
         HWND hWnd,
         LPRECT lpRect);

Here is the wrapping with `ctypes`:

    >>> from ctypes import POINTER, WINFUNCTYPE, windll, WinError
    >>> from ctypes.wintypes import BOOL, HWND, RECT
    >>> prototype = WINFUNCTYPE(BOOL, HWND, POINTER(RECT))
    >>> paramflags = (1, "hwnd"), (2, "lprect")
    >>> GetWindowRect = prototype(("GetWindowRect", windll.user32), paramflags)
    >>>

Функції з вихідними параметрами автоматично повертатимуть значення вихідного параметра, якщо є одне, або кортеж, що містить значення вихідних параметрів, якщо їх декілька, тому функція GetWindowRect тепер повертає екземпляр RECT під час виклику.

Output parameters can be combined with the `errcheck` protocol to do further output processing and error checking. The win32 `GetWindowRect` api function returns a `BOOL` to signal success or failure, so this function could do the error checking, and raises an exception when the api call failed:

    >>> def errcheck(result, func, args):
    ...     if not result:
    ...         raise WinError()
    ...     return args
    ...
    >>> GetWindowRect.errcheck = errcheck
    >>>

If the `errcheck` function returns the argument tuple it receives unchanged, `ctypes` continues the normal processing it does on the output parameters. If you want to return a tuple of window coordinates instead of a `RECT` instance, you can retrieve the fields in the function and return them instead, the normal processing will no longer take place:

    >>> def errcheck(result, func, args):
    ...     if not result:
    ...         raise WinError()
    ...     rc = args[1]
    ...     return rc.left, rc.top, rc.bottom, rc.right
    ...
    >>> GetWindowRect.errcheck = errcheck
    >>>

### Функції корисності

ctypes.addressof(obj)

  Повертає адресу буфера пам’яті як ціле число. obj має бути екземпляром типу ctypes.

  Викликає подію аудиту `ctypes.addressof` з аргументом `obj`.

ctypes.alignment(obj_or_type)

  Повертає вимоги до вирівнювання типу ctypes. obj_or_type має бути типом або екземпляром ctypes.

ctypes.byref(obj[, offset])

  Повертає легкий вказівник на obj, який має бути екземпляром типу ctypes. offset за замовчуванням дорівнює нулю і має бути цілим числом, яке буде додано до значення внутрішнього покажчика.

  `byref(obj, offset)` відповідає цьому коду C:

      (((char *)&obj) + offset)

  Повернений об’єкт можна використовувати лише як параметр виклику зовнішньої функції. Він поводиться подібно до `pointer(obj)`, але будівництво відбувається набагато швидше.

ctypes.CopyComPointer(src, dst)

  Copies a COM pointer from src to dst and returns the Windows specific `HRESULT` value.

  If src is not `NULL`, its `AddRef` method is called, incrementing the reference count.

  In contrast, the reference count of dst will not be decremented before assigning the new value. Unless dst is `NULL`, the caller is responsible for decrementing the reference count by calling its `Release` method when necessary.

  Availability: Windows

  Added in version 3.14.

ctypes.cast(obj, type)

  Ця функція схожа на оператор приведення в C. Вона повертає новий екземпляр type, який вказує на той самий блок пам’яті, що й obj. type має бути типом покажчика, а obj має бути об’єктом, який можна інтерпретувати як покажчик.

ctypes.create_string_buffer(init, size=None)
ctypes.create_string_buffer(size)

  Ця функція створює змінний символьний буфер. Повернений об’єкт є масивом ctypes `c_char`.

  If size is given (and not `None`), it must be an `int`. It specifies the size of the returned array.

  If the init argument is given, it must be `bytes`. It is used to initialize the array items. Bytes not initialized this way are set to zero (NUL).

  If size is not given (or if it is `None`), the buffer is made one element larger than init, effectively adding a NUL terminator.

  If both arguments are given, size must not be less than `len(init)`.

  Попередження

  If size is equal to `len(init)`, a NUL terminator is not added. Do not treat such a buffer as a C string.

  For example:

      >>> bytes(create_string_buffer(2))
      b'\x00\x00'
      >>> bytes(create_string_buffer(b'ab'))
      b'ab\x00'
      >>> bytes(create_string_buffer(b'ab', 2))
      b'ab'
      >>> bytes(create_string_buffer(b'ab', 4))
      b'ab\x00\x00'
      >>> bytes(create_string_buffer(b'abcdef', 2))
      Traceback (most recent call last):
         ...
      ValueError: byte string too long

  Викликає подію аудиту `ctypes.create_string_buffer` з аргументами `init`, `size`.

ctypes.create_unicode_buffer(init, size=None)
ctypes.create_unicode_buffer(size)

  Ця функція створює змінний буфер символів Unicode. Повернений об’єкт є масивом ctypes `c_wchar`.

  The function takes the same arguments as `create_string_buffer()` except init must be a string and size counts `c_wchar`.

  Викликає подію аудиту `ctypes.create_unicode_buffer` з аргументами `init`, `size`.

ctypes.DllCanUnloadNow()

  This function is a hook which allows implementing in-process COM servers with ctypes. It is called from the DllCanUnloadNow function that the _ctypes extension dll exports.

  Availability: Windows

ctypes.DllGetClassObject()

  This function is a hook which allows implementing in-process COM servers with ctypes. It is called from the DllGetClassObject function that the `_ctypes` extension dll exports.

  Availability: Windows

ctypes.util.find_library(name)

  Спробуйте знайти бібліотеку та повернути шлях. ім’я — це ім’я бібліотеки без будь-яких префіксів, як-от `lib`, суфіксів, як-от `.so`, `.dylib` або номера версії (це форма, яка використовується для параметра компонувальника posix `-l`). Якщо бібліотеки не знайдено, повертає `None`.

  Точна функція залежить від системи.

  See Пошук спільних бібліотек for complete documentation.

ctypes.util.find_msvcrt()

  Returns the filename of the VC runtime library used by Python, and by the extension modules. If the name of the library cannot be determined, `None` is returned.

  Якщо вам потрібно звільнити пам’ять, наприклад, виділену модулем розширення за допомогою виклику `free(void *)`, важливо, щоб ви використовували функцію в тій самій бібліотеці, яка виділила пам’ять.

  Availability: Windows

ctypes.util.dllist()

  Try to provide a list of paths of the shared libraries loaded into the current process. These paths are not normalized or processed in any way. The function can raise `OSError` if the underlying platform APIs fail. The exact functionality is system dependent.

  On most platforms, the first element of the list represents the current executable file. It may be an empty string.

  Availability: Windows, macOS, iOS, glibc, BSD libc, musl

  Added in version 3.14.

ctypes.FormatError([code])

  Returns a textual description of the error code code. If no error code is specified, the last error code is used by calling the Windows API function `GetLastError()`.

  Availability: Windows

ctypes.GetLastError()

  Returns the last error code set by Windows in the calling thread. This function calls the Windows `GetLastError()` function directly, it does not return the ctypes-private copy of the error code.

  Availability: Windows

ctypes.get_errno()

  Повертає поточне значення ctypes-private копії системної змінної `errno` у потоці виклику.

  Викликає подію аудиту `ctypes.get_errno` без аргументів.

ctypes.get_last_error()

  Returns the current value of the ctypes-private copy of the system `LastError` variable in the calling thread.

  Availability: Windows

  Викликає подію аудиту `ctypes.get_last_error` без аргументів.

ctypes.memmove(dst, src, count)

  Те саме, що стандартна функція бібліотеки C memmove: копіює count байти з src до dst. dst і src мають бути цілими числами або екземплярами ctypes, які можна перетворити на покажчики.

ctypes.memset(dst, c, count)

  Те саме, що стандартна функція бібліотеки memset C: заповнює блок пам’яті за адресою dst count байтами зі значенням c. dst має бути цілим числом, що визначає адресу, або екземпляр ctypes.

ctypes.POINTER(type, /)

  Create or return a ctypes pointer type. Pointer types are cached and reused internally, so calling this function repeatedly is cheap. type must be a ctypes type.

  Деталі реалізації CPython: The resulting pointer type is cached in the `__pointer_type__` attribute of type. It is possible to set this attribute before the first call to `POINTER` in order to set a custom pointer type. However, doing this is discouraged: manually creating a suitable pointer type is difficult without relying on implementation details that may change in future Python versions.

ctypes.pointer(obj, /)

  Create a new pointer instance, pointing to obj. The returned object is of the type `POINTER(type(obj))`.

  Примітка. Якщо ви просто хочете передати вказівник на об’єкт у зовнішній виклик функції, вам слід використовувати `byref(obj)`, що набагато швидше.

ctypes.resize(obj, size)

  Ця функція змінює розмір буфера внутрішньої пам’яті obj, який має бути екземпляром типу ctypes. Неможливо зробити буфер меншим, ніж власний розмір типу об’єктів, як задано `sizeof(type(obj))`, але можна збільшити буфер.

ctypes.set_errno(value)

  Установіть поточне значення ctypes-private копії системної змінної `errno` у викликаючому потоці на value і поверніть попереднє значення.

  Викликає подію аудиту `ctypes.set_errno` з аргументом `errno`.

ctypes.set_last_error(value)

  Sets the current value of the ctypes-private copy of the system `LastError` variable in the calling thread to value and return the previous value.

  Availability: Windows

  Викликає подію аудиту `ctypes.set_last_error` з аргументом `помилка`.

ctypes.sizeof(obj_or_type)

  Повертає розмір у байтах типу ctypes або буфера пам’яті примірника. Діє так само, як і оператор C `sizeof`.

ctypes.string_at(ptr, size=-1)

  Return the byte string at void *ptr. If size is specified, it is used as size, otherwise the string is assumed to be zero-terminated.

  Raises an auditing event `ctypes.string_at` with arguments `ptr`, `size`.

ctypes.WinError(code=None, descr=None)

  Creates an instance of `OSError`. If code is not specified, `GetLastError()` is called to determine the error code. If descr is not specified, `FormatError()` is called to get a textual description of the error.

  Availability: Windows

  Змінено в версії 3.3: An instance of `WindowsError` used to be created, which is now an alias of `OSError`.

ctypes.wstring_at(ptr, size=-1)

  Return the wide-character string at void *ptr. If size is specified, it is used as the number of characters of the string, otherwise the string is assumed to be zero-terminated.

  Raises an auditing event `ctypes.wstring_at` with arguments `ptr`, `size`.

ctypes.memoryview_at(ptr, size, readonly=False)

  Return a `memoryview` object of length size that references memory starting at void *ptr.

  If readonly is true, the returned `memoryview` object can not be used to modify the underlying memory. (Changes made by other means will still be reflected in the returned object.)

  This function is similar to `string_at()` with the key difference of not making a copy of the specified memory. It is a semantically equivalent (but more efficient) alternative to `memoryview((c_byte * size).from_address(ptr))`. (While `from_address()` only takes integers, ptr can also be given as a `ctypes.POINTER` or a `byref()` object.)

  Raises an auditing event `ctypes.memoryview_at` with arguments `address`, `size`, `readonly`.

  Added in version 3.14.

### Типи даних

class ctypes._CData

  Цей непублічний клас є загальним базовим класом для всіх типів даних ctypes. Серед іншого, усі екземпляри типу ctypes містять блок пам’яті, який містить C-сумісні дані; адреса блоку пам’яті повертається допоміжною функцією `addressof()`. Інша змінна екземпляра представлена як `_objects`; це містить інші об’єкти Python, які потрібно підтримувати в активному стані, якщо блок пам’яті містить покажчики.

  Загальні методи типів даних ctypes, це всі методи класу (точніше, це методи metaclass):

  from_buffer(source[, offset])

    Цей метод повертає екземпляр ctypes, який спільно використовує буфер об’єкта source. Об’єкт джерело має підтримувати інтерфейс буфера з можливістю запису. Необов’язковий параметр offset визначає зсув у вихідному буфері в байтах; за замовчуванням дорівнює нулю. Якщо вихідний буфер недостатньо великий, виникає `ValueError`.

    Викликає подію аудиту `ctypes.cdata/buffer` з аргументами `pointer`, `size`, `offset`.

  from_buffer_copy(source[, offset])

    Цей метод створює екземпляр ctypes, копіюючи буфер із буфера джерельного об’єкта, який має бути читабельним. Необов’язковий параметр offset визначає зсув у вихідному буфері в байтах; за замовчуванням дорівнює нулю. Якщо вихідний буфер недостатньо великий, виникає `ValueError`.

    Викликає подію аудиту `ctypes.cdata/buffer` з аргументами `pointer`, `size`, `offset`.

  from_address(address)

    Цей метод повертає екземпляр типу ctypes, використовуючи пам’ять, визначену адресою, яка має бути цілим числом.

    Цей метод та інші, які опосередковано викликають цей метод, викликають подію аудиту `ctypes.cdata` з аргументом `адреса`.

  from_param(obj)

    This method adapts obj to a ctypes type. It is called with the actual object used in a foreign function call when the type is present in the foreign function’s `argtypes` tuple; it must return an object that can be used as a function call parameter.

    Усі типи даних ctypes мають стандартну реалізацію цього методу класу, який зазвичай повертає obj, якщо це екземпляр типу. Деякі типи також приймають інші об’єкти.

  in_dll(library, name)

    Цей метод повертає екземпляр типу ctypes, експортований спільною бібліотекою. name — це ім’я символу, який експортує дані, library — це завантажена спільна бібліотека.

  Common class variables of ctypes data types:

  __pointer_type__

    The pointer type that was created by calling `POINTER()` for corresponding ctypes data type. If a pointer type was not yet created, the attribute is missing.

    Added in version 3.14.

  Загальні змінні екземплярів типів даних ctypes:

  _b_base_

    Іноді екземпляри даних ctypes не володіють блоком пам’яті, який вони містять, натомість вони спільно використовують частину блоку пам’яті базового об’єкта. Член `_b_base_` лише для читання є кореневим об’єктом ctypes, якому належить блок пам’яті.

  _b_needsfree_

    Ця змінна лише для читання є істиною, коли екземпляр даних ctypes сам виділив блок пам’яті, інакше – false.

  _objects

    Цей член або `None`, або словник, що містить об’єкти Python, які потрібно підтримувати в активному стані, щоб вміст блоку пам’яті залишався дійсним. Цей об’єкт доступний лише для налагодження; ніколи не змінюйте вміст цього словника.

### Основні типи даних

class ctypes._SimpleCData

  Цей закритий клас є базовим класом усіх основних типів даних ctypes. Він згадується тут, оскільки він містить загальні атрибути основних типів даних ctypes. `_SimpleCData` є підкласом `_CData`, тому він успадковує їхні методи та атрибути. Типи даних ctypes, які не є та не містять покажчиків, тепер можна маринувати.

  Екземпляри мають один атрибут:

  value

    Цей атрибут містить фактичне значення екземпляра. Для цілочисельних типів і типів покажчиків це ціле число, для типів символів – об’єкт або рядок із одним символом у байтах, для типів покажчиків на символи – це об’єкт або рядок Python bytes.

    When the `value` attribute is retrieved from a ctypes instance, usually a new object is returned each time. `ctypes` does not implement original object return, always a new object is constructed. The same is true for all other ctypes object instances.

Fundamental data types, when returned as foreign function call results, or, for example, by retrieving structure field members or array items, are transparently converted to native Python types. In other words, if a foreign function has a `restype` of `c_char_p`, you will always receive a Python bytes object, not a `c_char_p` instance.

Subclasses of fundamental data types do not inherit this behavior. So, if a foreign functions `restype` is a subclass of `c_void_p`, you will receive an instance of this subclass from the function call. Of course, you can get the value of the pointer by accessing the `value` attribute.

Ось основні типи даних ctypes:

class ctypes.c_byte

  Represents the C signed char datatype, and interprets the value as small integer. The constructor accepts an optional integer initializer; no overflow checking is done.

class ctypes.c_char

  Represents the C char datatype, and interprets the value as a single character. The constructor accepts an optional string initializer, the length of the string must be exactly one character.

class ctypes.c_char_p

  Represents the C char* datatype when it points to a zero-terminated string. For a general character pointer that may also point to binary data, `POINTER(c_char)` must be used. The constructor accepts an integer address, or a bytes object.

class ctypes.c_double

  Represents the C double datatype. The constructor accepts an optional float initializer.

class ctypes.c_longdouble

  Represents the C long double datatype. The constructor accepts an optional float initializer. On platforms where `sizeof(long double) == sizeof(double)` it is an alias to `c_double`.

class ctypes.c_float

  Represents the C float datatype. The constructor accepts an optional float initializer.

class ctypes.c_double_complex

  Represents the C double complex datatype, if available. The constructor accepts an optional `complex` initializer.

  Added in version 3.14.

class ctypes.c_float_complex

  Represents the C float complex datatype, if available. The constructor accepts an optional `complex` initializer.

  Added in version 3.14.

class ctypes.c_longdouble_complex

  Represents the C long double complex datatype, if available. The constructor accepts an optional `complex` initializer.

  Added in version 3.14.

class ctypes.c_int

  Represents the C signed int datatype. The constructor accepts an optional integer initializer; no overflow checking is done. On platforms where `sizeof(int) == sizeof(long)` it is an alias to `c_long`.

class ctypes.c_int8

  Represents the C 8-bit signed int datatype. It is an alias for `c_byte`.

class ctypes.c_int16

  Represents the C 16-bit signed int datatype. Usually an alias for `c_short`.

class ctypes.c_int32

  Represents the C 32-bit signed int datatype. Usually an alias for `c_int`.

class ctypes.c_int64

  Represents the C 64-bit signed int datatype. Usually an alias for `c_longlong`.

class ctypes.c_long

  Represents the C signed long datatype. The constructor accepts an optional integer initializer; no overflow checking is done.

class ctypes.c_longlong

  Represents the C signed long long datatype. The constructor accepts an optional integer initializer; no overflow checking is done.

class ctypes.c_short

  Represents the C signed short datatype. The constructor accepts an optional integer initializer; no overflow checking is done.

class ctypes.c_size_t

  Представляє тип даних C `size_t`.

class ctypes.c_ssize_t

  Представляє тип даних C `ssize_t`.

  Added in version 3.2.

class ctypes.c_time_t

  Represents the C `time_t` datatype.

  Added in version 3.12.

class ctypes.c_ubyte

  Represents the C unsigned char datatype, it interprets the value as small integer. The constructor accepts an optional integer initializer; no overflow checking is done.

class ctypes.c_uint

  Represents the C unsigned int datatype. The constructor accepts an optional integer initializer; no overflow checking is done. On platforms where `sizeof(int) == sizeof(long)` it is an alias for `c_ulong`.

class ctypes.c_uint8

  Represents the C 8-bit unsigned int datatype. It is an alias for `c_ubyte`.

class ctypes.c_uint16

  Represents the C 16-bit unsigned int datatype. Usually an alias for `c_ushort`.

class ctypes.c_uint32

  Represents the C 32-bit unsigned int datatype. Usually an alias for `c_uint`.

class ctypes.c_uint64

  Represents the C 64-bit unsigned int datatype. Usually an alias for `c_ulonglong`.

class ctypes.c_ulong

  Represents the C unsigned long datatype. The constructor accepts an optional integer initializer; no overflow checking is done.

class ctypes.c_ulonglong

  Represents the C unsigned long long datatype. The constructor accepts an optional integer initializer; no overflow checking is done.

class ctypes.c_ushort

  Represents the C unsigned short datatype. The constructor accepts an optional integer initializer; no overflow checking is done.

class ctypes.c_void_p

  Represents the C void* type. The value is represented as integer. The constructor accepts an optional integer initializer.

class ctypes.c_wchar

  Представляє тип даних C `wchar_t` і інтерпретує значення як односимвольний рядок Unicode. Конструктор приймає необов’язковий ініціалізатор рядка, довжина рядка має бути рівно одному символу.

class ctypes.c_wchar_p

  Represents the C wchar_t* datatype, which must be a pointer to a zero-terminated wide character string. The constructor accepts an integer address, or a string.

class ctypes.c_bool

  Represent the C bool datatype (more accurately, _Bool from C99). Its value can be `True` or `False`, and the constructor accepts any object that has a truth value.

class ctypes.HRESULT

  Represents a `HRESULT` value, which contains success or error information for a function or method call.

  Availability: Windows

class ctypes.py_object

  Represents the C PyObject* datatype. Calling this without an argument creates a `NULL` PyObject* pointer.

  Змінено в версії 3.14: `py_object` is now a generic type.

The `ctypes.wintypes` module provides quite some other Windows specific data types, for example `HWND`, `WPARAM`, or `DWORD`. Some useful structures like `MSG` or `RECT` are also defined.

### Структуровані типи даних

class ctypes.Union(*args, **kw)

  Абстрактний базовий клас для об’єднань у рідному порядку байтів.

  Unions share common attributes and behavior with structures; see `Structure` documentation for details.

class ctypes.BigEndianUnion(*args, **kw)

  Abstract base class for unions in big endian byte order.

  Added in version 3.11.

class ctypes.LittleEndianUnion(*args, **kw)

  Abstract base class for unions in little endian byte order.

  Added in version 3.11.

class ctypes.BigEndianStructure(*args, **kw)

  Абстрактний базовий клас для структур у великому порядку байтів.

class ctypes.LittleEndianStructure(*args, **kw)

  Абстрактний базовий клас для структур у порядку байтів little endian.

Structures and unions with non-native byte order cannot contain pointer type fields, or any other data types containing pointer type fields.

class ctypes.Structure(*args, **kw)

  Абстрактний базовий клас для структур у власному порядку байтів.

  Concrete structure and union types must be created by subclassing one of these types, and at least define a `_fields_` class variable. `ctypes` will create descriptors which allow reading and writing the fields by direct attribute accesses. These are the

  _fields_

    Послідовність, що визначає поля структури. Елементи мають бути 2-кортежними або 3-кортежними. Перший пункт – ім’я поля, другий – тип поля; це може бути будь-який тип даних ctypes.

    Для полів цілого типу, таких як `c_int`, можна вказати третій необов’язковий елемент. Це має бути маленьке позитивне ціле число, що визначає розрядність поля.

    Імена полів мають бути унікальними в межах однієї структури чи об’єднання. Це не позначено, лише одне поле доступне, якщо імена повторюються.

    Можна визначити змінну класу `_fields_` після оператора класу, який визначає підклас Structure, це дозволяє створювати типи даних, які прямо чи опосередковано посилаються на себе:

        class List(Structure):
            pass
        List._fields_ = [("pnext", POINTER(List)),
                         ...
                        ]

    The `_fields_` class variable can only be set once. Later assignments will raise an `AttributeError`.

    Additionally, the `_fields_` class variable must be defined before the structure or union type is first used: an instance or subclass is created, `sizeof()` is called on it, and so on. Later assignments to `_fields_` will raise an `AttributeError`. If `_fields_` has not been set before such use, the structure or union will have no own fields, as if `_fields_` was empty.

    Sub-subclasses of structure types inherit the fields of the base class plus the `_fields_` defined in the sub-subclass, if any.

  _pack_

    An optional small integer that allows overriding the alignment of structure fields in the instance.

    This is only implemented for the MSVC-compatible memory layout (see `_layout_`).

    Setting `_pack_` to 0 is the same as not setting it at all. Otherwise, the value must be a positive power of two. The effect is equivalent to `#pragma pack(N)` in C, except `ctypes` may allow larger n than what the compiler accepts.

    `_pack_` must already be defined when `_fields_` is assigned, otherwise it will have no effect.

    Deprecated since version 3.14, will be removed in version 3.19: For historical reasons, if `_pack_` is non-zero, the MSVC-compatible layout will be used by default. On non-Windows platforms, this default is deprecated and is slated to become an error in Python 3.19. If it is intended, set `_layout_` to `'ms'` explicitly.

  _align_

    An optional small integer that allows increasing the alignment of the structure when being packed or unpacked to/from memory.

    The value must not be negative. The effect is equivalent to `__attribute__((aligned(N)))` on GCC or `#pragma align(N)` on MSVC, except `ctypes` may allow values that the compiler would reject.

    `_align_` can only increase a structure’s alignment requirements. Setting it to 0 or 1 has no effect.

    Using values that are not powers of two is discouraged and may lead to surprising behavior.

    `_align_` must already be defined when `_fields_` is assigned, otherwise it will have no effect.

    Added in version 3.13.

  _layout_

    An optional string naming the struct/union layout. It can currently be set to:

    - `"ms"`: the layout used by the Microsoft compiler (MSVC). On GCC and Clang, this layout can be selected with `__attribute__((ms_struct))`.

    - `"gcc-sysv"`: the layout used by GCC with the System V or “SysV-like” data model, as used on Linux and macOS. With this layout, `_pack_` must be unset or zero.

    If not set explicitly, `ctypes` will use a default that matches the platform conventions. This default may change in future Python releases (for example, when a new platform gains official support, or when a difference between similar platforms is found). Currently the default will be:

    - On Windows: `"ms"`

    - When `_pack_` is specified: `"ms"`. (This is deprecated; see `_pack_` documentation.)

    - Otherwise: `"gcc-sysv"`

    `_layout_` must already be defined when `_fields_` is assigned, otherwise it will have no effect.

    Added in version 3.14.

  _anonymous_

    Необов’язкова послідовність, яка містить імена безіменних (анонімних) полів. `_anonymous_` має бути вже визначено під час призначення `_fields_`, інакше це не матиме ефекту.

    The fields listed in this variable must be structure or union type fields. `ctypes` will create descriptors in the structure type that allows accessing the nested fields directly, without the need to create the structure or union field.

    Ось приклад типу (Windows):

        class _U(Union):
            _fields_ = [("lptdesc", POINTER(TYPEDESC)),
                        ("lpadesc", POINTER(ARRAYDESC)),
                        ("hreftype", HREFTYPE)]

        class TYPEDESC(Structure):
            _anonymous_ = ("u",)
            _fields_ = [("u", _U),
                        ("vt", VARTYPE)]

    Структура `TYPEDESC` описує тип даних COM, поле `vt` визначає, яке з полів об’єднання є дійсним. Оскільки поле `u` визначено як анонімне поле, тепер можна отримати доступ до членів безпосередньо з примірника TYPEDESC. `td.lptdesc` і `td.u.lptdesc` еквівалентні, але перший швидший, оскільки йому не потрібно створювати тимчасовий екземпляр об’єднання:

        td = TYPEDESC()
        td.vt = VT_PTR
        td.lptdesc = POINTER(some_type)
        td.u.lptdesc = POINTER(some_type)

  Є можливість визначення суб-підкласів структур, вони успадковують поля базового класу. Якщо визначення підкласу має окрему змінну `_fields_`, поля, зазначені в ній, додаються до полів базового класу.

  Конструктори структури та об’єднання приймають як позиційні, так і ключові аргументи. Позиційні аргументи використовуються для ініціалізації полів-членів у такому самому порядку, як вони з’являються в `_fields_`. Аргументи ключових слів у конструкторі інтерпретуються як призначення атрибутів, тому вони ініціалізують `_fields_` з тим же іменем або створять нові атрибути для імен, яких немає в `_fields_`.

class ctypes.CField(*args, **kw)

  Descriptor for fields of a `Structure` and `Union`. For example:

      >>> class Color(Structure):
      ...     _fields_ = (
      ...         ('red', c_uint8),
      ...         ('green', c_uint8),
      ...         ('blue', c_uint8),
      ...         ('intense', c_bool, 1),
      ...         ('blinking', c_bool, 1),
      ...    )
      ...
      >>> Color.red
      <ctypes.CField 'red' type=c_ubyte, ofs=0, size=1>
      >>> Color.green.type
      <class 'ctypes.c_ubyte'>
      >>> Color.blue.byte_offset
      2
      >>> Color.intense
      <ctypes.CField 'intense' type=c_bool, ofs=3, bit_size=1, bit_offset=0>
      >>> Color.blinking.bit_offset
      1

  All attributes are read-only.

  `CField` objects are created via `_fields_`; do not instantiate the class directly.

  Added in version 3.14: Previously, descriptors only had `offset` and `size` attributes and a readable string representation; the `CField` class was not available directly.

  name

    Name of the field, as a string.

  type

    Type of the field, as a ctypes class.

  offset
  byte_offset

    Offset of the field, in bytes.

    For bitfields, this is the offset of the underlying byte-aligned storage unit; see `bit_offset`.

  byte_size

    Size of the field, in bytes.

    For bitfields, this is the size of the underlying storage unit. Typically, it has the same size as the bitfield’s type.

  size

    For non-bitfields, equivalent to `byte_size`.

    For bitfields, this contains a backwards-compatible bit-packed value that combines `bit_size` and `bit_offset`. Prefer using the explicit attributes instead.

  is_bitfield

    True if this is a bitfield.

  bit_offset
  bit_size

    The location of a bitfield within its storage unit, that is, within `byte_size` bytes of memory starting at `byte_offset`.

    To get the field’s value, read the storage unit as an integer, shift left by `bit_offset` and take the `bit_size` least significant bits.

    For non-bitfields, `bit_offset` is zero and `bit_size` is equal to `byte_size * 8`.

  is_anonymous

    True if this field is anonymous, that is, it contains nested sub-fields that should be merged into a containing structure or union.

### Масиви та покажчики

class ctypes.Array(*args)

  Абстрактний базовий клас для масивів.

  The recommended way to create concrete array types is by multiplying any `ctypes` data type with a non-negative integer. Alternatively, you can subclass this type and define `_length_` and `_type_` class variables. Array elements can be read and written using standard subscript and slice accesses; for slice reads, the resulting object is not itself an `Array`.

  _length_

    Додатне ціле число, що визначає кількість елементів у масиві. Індекси поза діапазоном призводять до `IndexError`. Буде повернено `len()`.

  _type_

    Визначає тип кожного елемента в масиві.

  Конструктори підкласу масиву приймають позиційні аргументи, які використовуються для ініціалізації елементів у порядку.

ctypes.ARRAY(type, length)

  Create an array. Equivalent to `type * length`, where type is a `ctypes` data type and length an integer.

  This function is soft deprecated in favor of multiplication. There are no plans to remove it.

class ctypes._Pointer

  Приватний, абстрактний базовий клас для вказівників.

  Конкретні типи вказівників створюються шляхом виклику `POINTER()` із типом, на який буде вказувати; це робиться автоматично за допомогою `pointer()`.

  Якщо вказівник вказує на масив, його елементи можна читати та записувати за допомогою стандартного підрядкового і зрізного доступу. Об’єкти-вказівники не мають розміру, тому `len()` викличе `TypeError`. Негативні індекси читатимуться з пам’яті перед вказівником (як у C), а індекси поза межами діапазону, ймовірно, впадуть із порушенням доступу (якщо вам пощастить).

  _type_

    Визначає тип, на який вказується.

  contents

    Повертає об’єкт, на який вказує вказівник. Призначення цьому атрибуту змінює вказівник на призначений об’єкт.

### Exceptions

exception ctypes.ArgumentError

  Цей виняток виникає, коли зовнішній виклик функції не може перетворити один із переданих аргументів.

exception ctypes.COMError(hresult, text, details)

  This exception is raised when a COM method call failed.

  hresult

    The integer value representing the error code.

  text

    The error message.

  details

    The 5-tuple `(descr, source, helpfile, helpcontext, progid)`.

    descr is the textual description. source is the language-dependent `ProgID` for the class or application that raised the error. helpfile is the path of the help file. helpcontext is the help context identifier. progid is the `ProgID` of the interface that defined the error.

  Availability: Windows

  Added in version 3.14.