# `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 자습서

참고: 일부 코드 예제는 ctypes `c_int` 형을 참조합니다. `sizeof(long) == sizeof(int)`인 플랫폼에서, 이는 `c_long`의 별칭입니다. 따라서 `c_int`를 기대할 때 `c_long`가 인쇄되더라도 혼란스러워하지 않아도 됩니다 — 이것들은 실제로 같은 형입니다.

### 동적 링크 라이브러리 로드하기

`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에서 변경: 윈도우 에러는 `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
    >>>

윈도우는 일반적인 `.dll` 파일 접미사를 자동으로 추가합니다.

참고

`cdll.msvcrt`를 통해 표준 C 라이브러리에 액세스하면 파이썬에서 사용되는 라이브러리와 호환되지 않는 오래된 라이브러리 버전이 사용됩니다. 가능하면 파이썬 자체의 기능을 사용하거나, `msvcrt` 모듈을 임포트 해서 사용하십시오.

Other systems require 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.

For example, on Linux:

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

On macOS:

    >>> cdll.LoadLibrary("libc.dylib")
    <CDLL 'libc.dylib', handle ... at ...>
    >>> libc = CDLL("libc.dylib")
    >>> libc
    <CDLL 'libc.dylib', 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은 `"??2@YAPAXI@Z"`와 같은 유효한 파이썬 식별자가 아닌 이름으로 함수를 내보냅니다. 이때는 `getattr()`를 사용하여 함수를 조회해야 합니다:

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

윈도우에서, 일부 dll은 이름이 아니라 서수(ordinal)로 함수를 내보냅니다. 이 함수는 서수로 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
    >>>

`cdecl` 호출 규칙을 사용하여 `stdcall` 함수를 호출하면 `ValueError`가 발생하고, 그 반대도 마찬가지입니다:

    >>> 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 형 | C 형 | 파이썬 형 | `_type_`
--- | --- | --- | ---
`c_bool` | _Bool | `bool` | `'?'`
`c_char` | char | 1-character `bytes` | `'c'`
`c_wchar` | `wchar_t` | 1-character `str` | `'u'`
`c_byte` | char | `int` | `'b'`
`c_ubyte` | unsigned char | `int` | `'B'`
`c_short` | short | `int` | `'h'`
`c_ushort` | unsigned short | `int` | `'H'`
`c_int` | int | `int` | `'i'` *
`c_int8` | `int8_t` | `int` | *
`c_int16` | `int16_t` | `int` | *
`c_int32` | `int32_t` | `int` | *
`c_int64` | `int64_t` | `int` | *
`c_uint` | unsigned int | `int` | `'I'` *
`c_uint8` | `uint8_t` | `int` | *
`c_uint16` | `uint16_t` | `int` | *
`c_uint32` | `uint32_t` | `int` | *
`c_uint64` | `uint64_t` | `int` | *
`c_long` | long | `int` | `'l'`
`c_ulong` | unsigned long | `int` | `'L'`
`c_longlong` | long long | `int` | `'q'` *
`c_ulonglong` | unsigned long long | `int` | `'Q'` *
`c_size_t` | `size_t` | `int` | *
`c_ssize_t` | `Py_ssize_t` | `int` | *
`c_time_t` | `time_t` | `int` | *
`c_float` | float | `float` | `'f'`
`c_double` | double | `float` | `'d'`
`c_longdouble` | long double | `float` | `'g'` *
`c_char_p` | char* (NUL terminated) | `bytes` or `None` | `'z'`
`c_wchar_p` | wchar_t* (NUL terminated) | `str` or `None` | `'Z'`
`c_void_p` | void* | `int` or `None` | `'P'`
`py_object` | PyObject* | `object` | `'O'`
VARIANT_BOOL | short int | `bool` | `'v'`

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

ctypes 형 | C 형 | 파이썬 형 | `_type_`
--- | --- | --- | ---
`c_float_complex` | float complex | `complex` | `'Zf'`
`c_double_complex` | double complex | `complex` | `'Zd'`
`c_longdouble_complex` | long double complex | `complex` | `'Zg'`

버전 3.15에서 변경: The `_type_` types `F`, `D` and `G` have been replaced with `Zf`, `Zd` and `Zg`.

이 모든 형은 올바른 형과 값의 선택적 초기화자로 호출해서 만들어질 수 있습니다:

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

The constructors for numeric types will convert input using `__bool__()`, `__index__()` (for `int`), `__float__()` or `__complex__()`. This means `c_bool` accepts any object with a truth value:

    >>> empty_list = []
    >>> c_bool(empty_list)
    c_bool(False)

이러한 형은 가변이므로, 값을 나중에 변경할 수도 있습니다:

    >>> 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`는 윈도우 `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.

다음은 x 및 y라는 두 개의 정수가 포함된 POINT 구조체의 간단한 예제이며, 생성자에서 구조체를 초기화하는 방법도 보여줍니다:

    >>> 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
    >>>

그러나, 훨씬 복잡한 구조를 만들 수 있습니다. 구조체는 필드형으로 구조체를 사용하여 다른 구조체를 포함할 수 있습니다.

다음은 upperleft 및 lowerright라는 두 개의 POINT를 포함하는 RECT 구조체입니다:

    >>> 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개의 POINT를 포함하는 구조체입니다:

    >>> 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 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)
    >>>

포인터 인스턴스는 포인터가 가리키는 객체(위에서는 `i` 객체)를 반환하는 `contents` 어트리뷰트를 가집니다:

    >>> 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()`는 `Bar` 구조체의 `values` 필드에 대입하는 데 사용할 수 있습니다:

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

### 불완전한 형

불완전한 형은 멤버가 아직 지정되지 않은 구조체, 공용체 또는 배열입니다. C에서, 이것들은 나중에 정의되는 전방 선언(forward declaration)으로 지정됩니다:

    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` 호출 규칙을 사용하여 콜백 함수의 형을 만듭니다. 윈도우에서, `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.

따라서 콜백 함수는 정수에 대한 포인터들을 받고 정수를 반환해야 합니다. 먼저 콜백 함수를 위한 `형`을 만듭니다:

    >>> 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.

또한, 콜백 함수가 파이썬 제어 바깥에서 만들어진 스레드(예를 들어, 콜백을 호출하는 외부 코드)에서 호출되면, ctypes는 모든 호출에 대해 새로운 더미 파이썬 스레드를 만듭니다. 이 동작은 대부분 적합하지만, `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` 포인터에 액세스합니다.

해당 값에 대한 문서를 인용하면:

> 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
    >>>

표준 파이썬이 프로즌 모듈과 프로즌 패키지(음수 `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`은 기대하는 효과를 주지 못합니다.

Structure, Union 및 Array에서 서브 객체를 가져오는 것은 서브 객체를 복사하지 않고, 대신 루트 객체의 하부 버퍼에 액세스하는 래퍼 객체를 가져온다는 점에 유의하십시오.

예상과 다른 행동을 하는 또 다른 예는 다음과 같습니다:

    >>> 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`로 인스턴스를 만든 객체는 바이트열이나 정수로 설정된 value만 가질 수 있습니다.

`False`를 인쇄하는 이유는 무엇일까요? ctypes 인스턴스는 메모리 블록과 메모리 내용에 액세스하는 어떤 디스크립터를 포함하는 객체입니다. 메모리 블록에 파이썬 객체를 저장하면 객체 자체를 저장하지 않고, 대신 객체의 `내용`을 저장합니다. 내용에 다시 액세스하면 매번 새로운 파이썬 객체가 생성됩니다!

### 가변 크기 데이터형

`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 레퍼런스

### 공유 라이브러리 로드하기

There are several ways to load shared libraries into the Python process. One way is to instantiate `CDLL` or one of its subclasses:

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

  Represents a loaded shared library.

  Functions in this library use the standard C calling convention, and are assumed to return int. The Python global interpreter lock is released before calling any function exported by these libraries, and reacquired afterwards. For different function behavior, use a subclass: `OleDLL`, `WinDLL`, or `PyDLL`.

  If you have an existing `handle` to an already loaded shared library, it can be passed as the handle argument to wrap the opened library in a new `CDLL` object. In this case, name is only used to set the `_name` attribute, but it may be adjusted and/or validated.

  If handle is `None`, the underlying platform’s dlopen(3) or LoadLibraryExW function is used to load the library into the process, and to get a handle to it.

  name is the pathname of the shared library to open. If name does not contain a path separator, the library is found in a platform-specific way.

  On Windows, the `.DLL` suffix may be missing. (For details, see LoadLibraryExW documentation.) Other platform-specific prefixes and suffixes (for example, `lib`, `.so`, `.dylib`, or version numbers) must be present in name; they are not added automatically. See 공유 라이브러리 찾기 for more information.

  On non-Windows systems, name can be `None`. In this case, `dlopen()` is called with `NULL`, which opens the main program as a “library”. (Some systems do the same is name is empty; `None`/`NULL` is more portable.)

  CPython implementation detail

  Since CPython is linked to `libc`, a `None` name is often used to access the C standard library:

      >>> printf = ctypes.CDLL(None).printf
      >>> printf.argtypes = [ctypes.c_char_p]
      >>> printf(b"hello\n")
      hello
      6

  To access the Python C API, prefer `ctypes.pythonapi` which works across platforms.

  mode 매개 변수는 라이브러리가 로드되는 방법을 지정하는 데 사용될 수 있습니다. 자세한 내용은, dlopen(3) 매뉴얼 페이지를 참조하십시오. 윈도우에서는, mode가 무시됩니다. 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 LoadLibraryExW 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.

  윈도우에서는 DLL 이름이 존재하더라도 `CDLL` 인스턴스 생성이 실패할 수 있습니다. 로드된 DLL의 종속 DLL을 찾을 수 없을 때, “[WinError 126] The specified module could not be found” 메시지로 `OSError` 에러가 발생합니다. 윈도우 API가 정보를 반환하지 않아서 이 에러 메시지에는 누락된 DLL의 이름이 포함되어 있지 않고, 이 에러를 진단하기 어렵게 만듭니다. 이 에러를 해결하고 찾을 수 없는 DLL을 확인하려면, 윈도우 디버깅과 추적 도구를 사용하여 종속 DLL 목록을 찾고 찾을 수 없는 DLL을 확인해야 합니다.

  더 보기

  Microsoft DUMPBIN tool – A tool to find DLL dependents.

  버전 3.8에서 변경: winmode 매개 변수가 추가되었습니다.

  버전 3.12에서 변경: The name parameter can now be a path-like object.

  Instances of this class have no public methods. Functions exported by the shared library can be accessed as attributes or by index. Please note that accessing the function through an attribute caches the result and therefore accessing it repeatedly returns the same object each time. On the other hand, accessing it through an index returns a new object each time:

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

  The following public attributes are available. Their name starts with an underscore to not clash with exported function names:

  _handle

    라이브러리에 액세스하는 데 사용되는 시스템 핸들.

  _name

    생성자에서 전달된 라이브러리의 이름.

class ctypes.OleDLL

  See `CDLL`, the superclass, for common information.

  Functions in this library 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.

  가용성: Windows

  버전 3.3에서 변경: `WindowsError` used to be raised, which is now an alias of `OSError`.

class ctypes.WinDLL

  See `CDLL`, the superclass, for common information.

  Functions in these libraries use the `stdcall` calling convention, and are assumed to return int by default.

  가용성: Windows

class ctypes.PyDLL

  See `CDLL`, the superclass, for common information.

  When functions in this library are called, the Python GIL is not released during the function call, and after the function execution the Python error flag is checked. If the error flag is set, a Python exception is raised.

  Thus, this is only useful to call Python C API functions directly.

ctypes.RTLD_GLOBAL

  mode 매개 변수에 사용하는 플래그. 이 플래그를 사용할 수 없는 플랫폼에서는, 정수 0으로 정의됩니다.

ctypes.RTLD_LOCAL

  mode 매개 변수에 사용하는 플래그. 이 플래그를 사용할 수 없는 플랫폼에서는, RTLD_GLOBAL과 같습니다.

ctypes.DEFAULT_MODE

  공유 라이브러리를 로드하는 데 사용되는 기본 모드. OSX 10.3에서는 RTLD_GLOBAL이고, 그렇지 않으면 RTLD_LOCAL과 같습니다.

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.

>   가용성: Windows

> ctypes.oledll

>   Creates `OleDLL` instances.

>   가용성: Windows

> ctypes.pydll

>   `PyDLL` 인스턴스를 만듭니다.

> 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.

이러한 객체를 통해 라이브러리를 로드하면 라이브러리를 로드하는 데 사용된 이름인 `name` 문자열 인자로 감사 이벤트(auditing event) `ctypes.dlopen`을 발생시킵니다.

로드된 라이브러리에서 함수에 액세스하면 인자 `library`(라이브러리 객체)와 `name`(문자열이나 정수로 심볼의 이름)으로 감사 이벤트 `ctypes.dlsym`을 발생시킵니다.

객체 대신 라이브러리 핸들만 사용 가능한 경우, 함수에 액세스하면 인자 `handle`(원시 라이브러리 핸들)과 `name`으로 감사 이벤트 `ctypes.dlsym/handle`을 발생시킵니다.

### 공유 라이브러리 찾기

When programming in a compiled language, shared libraries are accessed when compiling/linking a program, and when the program is run. The programmer specifies a short name; the C compiler, linker, and runtime dynamic library loader then interact in system-specific ways to find the filename of the library to load.

While the mapping from short names to filenames is not consistently exposed by platforms, the `ctypes.util` module provides a function, `find_library()`, that attempts to match it. However, as backwards compatibility concerns make it difficult to adjust its behavior for new platforms and configurations, the function is soft deprecated.

If wrapping a shared library with `ctypes`, consider determining the shared library name at development time, and hardcoding it into the wrapper module instead of using `find_library()` to locate the library at runtime. Also consider adding a configuration option or environment variable to let users select a library to use, and then perhaps use `find_library()` as a default or fallback.

ctypes.util.find_library(name)

  Try to find a library and return a pathname.

  name is the “short” library name without any prefix like `lib`, suffix like `.so`, `.dylib` or version number. (This is the form used for the posix linker option `-l`.) The result is in a format suitable for passing to `CDLL`.

  If no library can be found, return `None`.

  The exact functionality is system dependent, and is not guaranteed to match the behavior of the compiler, linker, and loader used for (or by) Python. It is recommended to only use this function as a default or fallback,

  Soft deprecated since version 3.15: This function is kept for use in cases where it works, but not expected to be updated for additional platforms and configurations.

On Linux, `find_library()` tries to run external programs (`/sbin/ldconfig`, `gcc`, `objdump` and `ld`) to find the library file. 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에서 변경: 리눅스에서, 다른 수단으로 라이브러리를 찾을 수 없으면, 라이브러리 검색 시 환경 변수 `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`.

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. Notably, this will happen for recent versions of the VC runtime library, which are not directly loadable.

  예를 들어, `free(void *)`에 대한 호출로 확장 모듈에 의해 할당된 메모리를 해제해야 하면, 메모리를 할당한 것과 같은 라이브러리에 있는 함수를 사용하는 것이 중요합니다.

  가용성: Windows

### 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', ... ]

### 외부 함수

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

    이 어트리뷰트에 파이썬 함수나 다른 콜러블을 대입합니다. 콜러블은 3개 이상의 인자로 호출됩니다:

    callable(result, func, arguments)

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

      func는 외부 함수 객체 자체이며, 같은 콜러블 객체를 재사용하여 여러 함수의 결과를 확인하거나 사후 처리할 수 있도록 합니다.

      arguments는 원래 함수 호출에 전달된 매개 변수를 포함하는 튜플입니다. 사용된 인자에 따라 동작을 특수화할 수 있도록 합니다.

    이 함수가 반환하는 객체는 외부 함수 호출에서 반환되지만, 결괏값을 확인하고 외부 함수 호출이 실패하면 예외를 발생시킬 수도 있습니다.

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를 참으로 설정하면, 시스템 `errno` 변수의 ctypes 내부 복사본이 호출 전후에 실제 `errno` 값과 교환됩니다; use_last_error는 윈도우 에러 코드에 대해 같은 일을 합니다.

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.

  가용성: Windows

ctypes.PYFUNCTYPE(restype, *argtypes)

  반환된 함수 프로토타입은 파이썬 호출 규칙을 사용하는 함수를 만듭니다. 이 함수는 호출 도중 GIL을 해제하지 않습니다.

이러한 팩토리 함수로 만들어진 함수 프로토타입은 호출의 매개 변수 형과 수에 따라 다른 방법으로 인스턴스를 만들 수 있습니다:

prototype(address)

  지정된 정수 주소에 있는 외부 함수를 반환합니다.

prototype(callable)

  파이썬 callable로 C 호출 가능 함수(콜백 함수)를 만듭니다.

prototype(func_spec[, paramflags])

  공유 라이브러리가 내보낸 외부 함수를 반환합니다. func_spec은 2-튜플 `(name_or_ordinal, library)` 여야 합니다. 첫 번째 항목은 내보낸 함수의 문자열 이름이거나, 작은 정수로 표현된 내보낸 함수의 서수(ordinal)입니다. 두 번째 항목은 공유 라이브러리 인스턴스입니다.

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

  COM 메서드를 호출할 외부 함수를 반환합니다. vtbl_index는 가상 함수 테이블에 대한 인덱스이며, 작은 음이 아닌 정수입니다. name은 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.

  가용성: Windows

선택적 paramflags 매개 변수는 위에 설명된 기능보다 훨씬 많은 기능을 갖는 외부 함수 래퍼를 만듭니다.

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

이 튜플의 각 항목에는 매개 변수에 대한 추가 정보가 들어 있으며, 한 개, 두 개 또는 세 개의 항목이 들어있는 튜플이어야 합니다.

첫 번째 항목은 매개 변수의 방향 플래그 조합을 포함하는 정수입니다:

> 1

>   함수에 대한 입력 매개 변수를 지정합니다.

> 2

>   출력 매개 변수. 외부 함수가 값을 채웁니다.

> 4

>   기본값이 정수 0인 입력 매개 변수.

선택적인 두 번째 항목은 문자열 매개 변수 이름입니다. 이것이 지정되면, 이름있는 매개 변수로 외부 함수를 호출할 수 있습니다.

선택적 세 번째 항목은 이 매개 변수의 기본값입니다.

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")

두 번째 예제는 출력 매개 변수를 보여줍니다. win32 `GetWindowRect` 함수는 지정된 창의 크기를 조회하는데, 호출자가 제공해야 하는 `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 형의 인스턴스여야 합니다.

  인자 `obj`로 감사 이벤트 `ctypes.addressof`를 발생시킵니다.

ctypes.alignment(obj_or_type)

  ctypes 형의 정렬 요구 사항을 반환합니다. obj_or_type는 ctypes 형이나 인스턴스여야 합니다.

ctypes.byref(obj[, offset])

  obj에 대한 경량 포인터를 반환합니다. obj는 ctypes 형의 인스턴스여야 합니다. offset의 기본값은 0이며, 내부 포인터 값에 더해질 정수여야 합니다.

  `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.

  가용성: Windows

  Added in version 3.14.

ctypes.cast(obj, type)

  이 함수는 C의 형 변환 연산자와 유사합니다. obj와 같은 메모리 블록을 가리키는 type 형의 새 인스턴스를 반환합니다. type은 포인터형이어야 하며, obj는 포인터로 해석될 수 있는 객체여야 합니다.

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

  이 함수는 가변 문자 버퍼를 만듭니다. 반환된 객체는 `c_char`의 ctypes 배열입니다.

  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

  `init`, `size` 인자로 감사 이벤트 `ctypes.create_string_buffer`를 발생시킵니다.

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

  이 함수는 가변 유니코드 문자 버퍼를 만듭니다. 반환된 객체는 `c_wchar`의 ctypes 배열입니다.

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

  `init`, `size` 인자로 감사 이벤트 `ctypes.create_unicode_buffer`를 발생시킵니다.

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.

  가용성: 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.

  가용성: 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.

  가용성: 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()`.

  가용성: 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.

  가용성: Windows

ctypes.get_errno()

  호출하는 스레드에서 시스템 `errno` 변수의 ctypes 내부 복사본의 현재 값을 반환합니다.

  인자 없이 감사 이벤트 `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.

  가용성: Windows

  인자 없이 감사 이벤트 `ctypes.get_last_error`를 발생시킵니다.

ctypes.memmove(dst, src, count)

  표준 C memmove 라이브러리 함수와 같습니다: count 바이트를 src에서 dst로 복사합니다. dst 와 src는 정수이거나 포인터로 변환할 수 있는 ctypes 인스턴스여야 합니다.

ctypes.memset(dst, c, count)

  표준 C memset 라이브러리 함수와 같습니다: 주소 dst의 메모리 블록을 값 c의 count 바이트로 채웁니다. 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의 내부 메모리 버퍼의 크기를 조정합니다. obj는 ctypes 형의 인스턴스여야 합니다. `sizeof(type(obj))`로 주어지는 객체 형의 원래 크기보다 버퍼를 작게 만들 수는 없지만, 버퍼를 확대할 수 있습니다.

ctypes.set_errno(value)

  호출 중인 스레드의 시스템 `errno` 변수의 ctypes 내부 복사본의 현재 값을 value로 설정하고 이전 값을 반환합니다.

  인자 `errno`로 감사 이벤트 `ctypes.set_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.

  가용성: Windows

  인자 `error`로 감사 이벤트 `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.

  가용성: 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`로 노출됩니다; 여기에는 메모리 블록에 포인터가 포함되어있을 때, 살려둘 필요가 있는 다른 파이썬 객체가 포함되어 있습니다.

  ctypes 데이터형의 공통 메서드, 이것들은 모두 클래스 메서드입니다 (정확히 말하면, 메타 클래스의 메서드입니다):

  from_buffer(source[, offset])

    이 메서드는 source 객체의 버퍼를 공유하는 ctypes 인스턴스를 반환합니다. source 객체는 쓰기 가능한 버퍼 인터페이스를 지원해야 합니다. 선택적 offset 매개 변수는 source 버퍼의 오프셋을 바이트 단위로 지정합니다; 기본값은 0입니다. source 버퍼가 충분히 크지 않으면 `ValueError`가 발생합니다.

    인자 `pointer`, `size`, `offset`으로 감사 이벤트 `ctypes.cdata/buffer`를 발생시킵니다.

  from_buffer_copy(source[, offset])

    이 메서드는 읽을 수 있어야 하는 source 객체 버퍼에서 버퍼를 복사하여 ctypes 인스턴스를 만듭니다. 선택적 offset 매개 변수는 원본 버퍼의 오프셋을 바이트 단위로 지정합니다. 기본값은 0입니다. 소스 버퍼가 충분히 크지 않으면 `ValueError`가 발생합니다.

    인자 `pointer`, `size`, `offset`으로 감사 이벤트 `ctypes.cdata/buffer`를 발생시킵니다.

  from_address(address)

    이 메서드는 정수 address로 지정된 메모리를 사용하여 ctypes 형 인스턴스를 반환합니다.

    이 메서드와 이 메서드를 간접적으로 호출하는 다른 것들은 인자 `address`로 감사 이벤트 `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 가 이 형의 인스턴스면 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 데이터 인스턴스가 메모리 블록을 스스로 할당했을 때 참이고, 그렇지 않으면 거짓입니다.

  _objects

    이 멤버는 `None` 이거나 메모리 블록 내용이 계속 유효하도록 유지되어야 하는 파이썬 객체를 포함하는 딕셔너리입니다. 이 객체는 디버깅을 위해서만 노출됩니다; 이 딕셔너리의 내용을 수정하지 마십시오.

### 기본 데이터형

class ctypes._SimpleCData

  이 비공개 클래스는 모든 기본 ctypes 데이터형의 베이스 클래스입니다. 여기에는 기본 ctypes 데이터형의 공통 어트리뷰트가 들어 있으므로 여기에서 언급합니다. `_SimpleCData`는 `_CData`의 서브 클래스이므로, 메서드와 어트리뷰트를 상속받습니다. 포인터가 아니고 포인터를 포함하지 않는 ctypes 데이터형을 이제 피클 할 수 있습니다.

  인스턴스에는 어트리뷰트가 하나 있습니다:

  value

    이 어트리뷰트는 인스턴스의 실제 값을 포함합니다. 정수형과 포인터형에서는 정수고, 문자형에서는 단일 문자 바이트열 객체나 문자열이고, 문자 포인터형에서는 파이썬 바이트열 객체나 문자열입니다.

    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.

  Each subclass has a class attribute:

  _type_

    Class attribute that contains an internal type code, as a string. See 기본 데이터형 for a summary.

    Types marked * in the summary may be (or always are) aliases of a different `_SimpleCData` subclass, and will not necessarily use the listed type code. For example, if the platform’s long, long long and time_t C types are the same, then `c_long`, `c_longlong` and `c_time_t` all refer to a single class, `c_long`, whose `_type_` code is `'l'`. The `'L'` code will be unused.

    더 보기

    The `array` and struct modules, as well as third-party modules like numpy, use similar – but slightly different – type codes.

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. On platforms where `sizeof(long long) == sizeof(long)` it is an alias to `c_long`.

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

  Represents the C `size_t` datatype. Usually an alias for another unsigned integer type.

class ctypes.c_ssize_t

  Represents the `Py_ssize_t` datatype. This is a signed version of `size_t`; that is, the POSIX `ssize_t` type. Usually an alias for another integer type.

  Added in version 3.2.

class ctypes.c_time_t

  Represents the C `time_t` datatype. Usually an alias for another integer type.

  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. On platforms where `sizeof(long long) == sizeof(long)` it is an alias to `c_long`.

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` 데이터형을 나타내고, 값을 단일 문자 유니코드 문자열로 해석합니다. 생성자는 선택적 문자열 초기화자를 받아들입니다, 문자열의 길이는 정확히 한 문자여야 합니다.

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.

  가용성: 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`, `VARIANT_BOOL` 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)

  빅엔디안(big endian) 바이트 순서의 구조체를 위한 추상 베이스 클래스.

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_

    이름 없는(익명) 필드의 이름을 나열하는 선택적 시퀀스. `_fields_`가 대입될 때 `_anonymous_`는 이미 정의되어 있어야 합니다. 그렇지 않으면 아무 효과가 없습니다.

    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.

    다음은 예제 형입니다 (윈도우):

        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_

    배열의 각 요소 형을 지정합니다.

  Array 서브 클래스 생성자는 요소를 순서대로 초기화하는 데 사용되는 위치 인자를 받아들입니다.

ctypes.ARRAY(type, length)

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

  Soft deprecated since version 3.14: In favor of multiplication.

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.

  가용성: Windows

  Added in version 3.14.