ctypes --- Python 用の外部関数ライブラリ

ソースコード: Lib/ctypes


ctypes は Python のための外部関数ライブラリです。このライブラリは C と互換性のあるデータ型を提供し、動的リンク/共有ライブラリ内の関数呼び出しを可能にします。動的リンク/共有ライブラリを純粋な Python でラップするために使うことができます。

警告

ctypes provides low-level access to native libraries and the process's memory, bypassing Python's safety mechanisms and allowing execution of arbitrary native code. Incorrect use can corrupt data and objects, reveal sensitive information, cause crashes, or otherwise compromise the running process.

ctypes チュートリアル

注意: このチュートリアルのコードサンプルは動作確認のために doctest を使います。コードサンプルの中には Linux、 Windows、あるいは macOS 上で異なる動作をするものがあるため、サンプルのコメントに doctest 命令を入れてあります。

注意: いくつかのコードサンプルで ctypes の c_int 型を参照しています。 sizeof(long) == sizeof(int) であるようなプラットフォームでは、この型は c_long のエイリアスです。そのため、 c_int 型を想定しているときに c_long が表示されたとしても、混乱しないようにしてください --- 実際には同じ型なのです。

ロードした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
>>>

kernel32 や user32 などの win32 システム DLL は、関数の ANSI 版と UNICODE 版を両方エクスポートすることがよくあります。 UNICODE 版は名前の末尾に W、ANSI 版は A を付けてエクスポートされます。 指定したモジュール名の モジュールハンドル を返す win32 の GetModuleHandle 関数には、以下の C プロトタイプがあります。 UNICODE が定義されているかどうかに応じて、マクロが一方を GetModuleHandle として公開します。

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

windll は魔法を使ってどちらか一つを選ぶようなことはしません。GetModuleHandleA もしくは GetModuleHandleW を明示的に指定して必要とするバージョンにアクセスし、バイト列か文字列を使ってそれぞれ呼び出さなければなりません。

時には、 dll が関数を "??2@YAPAXI@Z" のような Python 識別子として有効でない名前でエクスポートすることがあります。このような場合に関数を取り出すには、 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
>>>

関数を呼び出す

これらの関数は、ほかの Python の呼び出し可能オブジェクトと同じように呼び出せます。 この例では、引数を取らず疑似乱数の整数を返す rand() 関数を使います。

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

Windows では、win32 モジュールハンドルを返す GetModuleHandleA() 関数を呼び出せます (唯一の引数に None を渡すと、NULL ポインタを渡して呼び出せます)。

>>> 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 ヘッダファイルもしくはドキュメントを見なければなりません。

Windows では、関数が無効な引数とともに呼び出された場合の一般保護例外によるクラッシュを防ぐために、 ctypes は win32 構造化例外処理を使います:

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

The faulthandler module can help debug crashes, such as segmentation faults produced by erroneous C library calls.

これらの関数呼び出しに引数として直接渡せる Python 標準のオブジェクトは、None、整数、バイト列オブジェクト、(Unicode) 文字列だけです。 None は C の NULL ポインタとして渡され、バイト列オブジェクトと文字列は、データを格納するメモリブロックへのポインタ (char* または wchar_t*) として渡されます。 Python の整数は、プラットフォームのデフォルトの C int 型として渡され、その C 型に収まるよう値がマスクされます。

他のパラメータ型をもつ関数呼び出しに移る前に、 ctypes データ型についてさらに学ぶ必要があります。

基本データ型

ctypes ではいくつもの C 互換のプリミティブなデータ型を定義しています:

ctypes の型

C の型

Python の型

c_bool

_Bool

bool (1)

c_char

char

1文字のバイト列オブジェクト

c_wchar

wchar_t

1文字の文字列

c_byte

char

int

c_ubyte

unsigned char

int

c_short

short

int

c_ushort

unsigned short

int

c_int

int

int

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

c_uint8

uint8_t

int

c_uint16

uint16_t

int

c_uint32

uint32_t

int

c_uint64

uint64_t

int

c_long

long

int

c_ulong

unsigned long

int

c_longlong

__int64 または long long

int

c_ulonglong

unsigned __int64 または unsigned long long

int

c_size_t

size_t

int

c_ssize_t

ssize_t or Py_ssize_t

int

c_time_t

time_t

int

c_float

float

浮動小数点数

c_double

double

浮動小数点数

c_longdouble

long double

浮動小数点数

c_char_p

char* (NUL 終端)

バイト列オブジェクトまたは None

c_wchar_p

wchar_t* (NUL 終端)

文字列または None

c_void_p

void*

整数または None

  1. コンストラクタは任意のオブジェクトをその真偽値として受け取ります。

これら全ての型はその型を呼び出すことによって作成でき、オプションとして型と値が合っている初期化子を指定することができます:

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

ポインタ型 c_char_p、c_wchar_p、c_void_p のインスタンスに新しい値を代入すると、そのポインタが指す メモリ位置 が変わり、メモリブロックの 内容は変わりません (Python の文字列オブジェクトは不変なので、当然の動作です)。

>>> 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)            # NUL バイトで初期化した 3 バイトのバッファを作成します
>>> print(sizeof(p), repr(p.raw))
3 b'\x00\x00\x00'
>>> p = create_string_buffer(b"Hello")     # NUL 終端文字列を含むバッファを作成します
>>> print(sizeof(p), repr(p.raw))
6 b'Hello\x00'
>>> print(repr(p.value))
b'Hello'
>>> p = create_string_buffer(b"Hello", 10) # 10 バイトのバッファを作成します
>>> 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'
>>>

create_string_buffer() 関数は、古い c_buffer() 関数を置き換えるものです (後者は別名として引き続き利用できます)。 C の wchar_t 型の Unicode 文字を格納する変更可能なメモリブロックを作成するには、create_unicode_buffer() 関数を使ってください。

続・関数を呼び出す

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

前に述べたように、必要な C のデータ型へ変換できるようにするためには、整数、文字列およびバイト列オブジェクトを除くすべての Python 型を対応する ctypes 型でラップしなければなりません:

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

可変長引数関数の呼び出し

多くのプラットフォームでは、ctypes を使った可変長引数関数の呼び出し方は、引数の数が固定の関数とまったく同じです。 一部のプラットフォーム、特に Apple プラットフォームの ARM64 では、可変長引数関数の呼び出し規約が通常の関数とは異なります。

それらのプラットフォームでは、可変長ではない通常の引数について argtypes 属性を指定する必要があります:

libc.printf.argtypes = [ctypes.c_char_p]

この属性の指定は移植性を損なわないため、すべての可変長引数関数について常に argtypes を指定することを推奨します。

自作のデータ型とともに関数を呼び出す

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.

要求される引数の型を指定する (関数プロトタイプ)

DLL がエクスポートする関数の引数に必要な型は、argtypes 属性を設定して指定できます。

argtypes は C のデータ型のシーケンスでなければなりません (printf() 関数は、書式文字列に応じて引数の数や型が変わるので、ここでは良い例とはいえませんが、この機能を試すには便利です)。

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

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

戻り値の型

デフォルトでは、関数は C の int 型を返すと仮定します。 関数オブジェクトの restype 属性を設定すれば、ほかの戻り値の型を指定できます。

time() の C プロトタイプは time_t time(time_t *) です。 time_t は、デフォルトの戻り値の型 int と異なる場合があるため、restype 属性を指定する必要があります。

>>> libc.time.restype = c_time_t

引数の型は argtypes を使って指定できます。

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

第 1 引数に NULL ポインタを渡して関数を呼び出すには、None を使います。

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

もう少し高度な例として、文字列へのポインタと char を受け取り、文字列へのポインタを返す strchr() 関数を使います。

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

上の例の ord("x") の呼び出しを省くには、argtypes 属性を設定します。 これにより、第 2 引数が 1 文字の Python バイト列オブジェクトから 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'
>>>

外部関数が整数を返す場合、restype 属性に、関数やクラスなどの Python の呼び出し可能オブジェクトを使うこともできます。 C 関数が返した 整数 を引数としてそのオブジェクトが呼び出され、その結果が関数呼び出しの結果として使われます。 これは、戻り値のエラーを検査して例外を自動的に送出するのに役立ちます。

>>> 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() を呼び出します。

errcheck 属性を使うと、さらに強力なエラー検査の仕組みを利用できます。 詳細はリファレンスマニュアルを参照してください。

ポインタを渡す(または、パラメータの参照渡し)

時には、 C api 関数がパラメータのデータ型として ポインタ を想定していることがあります。おそらくパラメータと同一の場所に書き込むためか、もしくはそのデータが大きすぎて値渡しできない場合です。これは パラメータの参照渡し としても知られています。

ctypes は byref() 関数をエクスポートしており、パラメータを参照渡しするために使用します。 pointer() 関数を使っても同じ効果が得られます。しかし、 pointer() は本当のポインタオブジェクトを構築するためより多くの処理を行うことから、 Python 側でポインタオブジェクト自体を必要としないならば byref() を使う方がより高速です。:

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

フィールド型は c_int か他の ctypes 型 (構造体、共用体、配列、ポインタ) から派生した ctypes 型である必要があります。

以下は、 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:

>>> print(POINT.x)
<Field type=c_long, ofs=0, size=4>
>>> print(POINT.y)
<Field type=c_long, ofs=4, size=4>
>>>

警告

ctypes では、ビットフィールドのある共用体や構造体の関数への値渡しはサポートしていません。これは 32-bit の x86 環境では動くかもしれませんが、このライブラリでは一般の場合に動作することは保証していません。

Structure/union alignment and byte order

By default, Structure and Union fields are aligned in the same way the C compiler does it. It is possible to override this behavior by specifying a _pack_ class attribute in the subclass definition. This must be set to a positive integer and specifies the maximum alignment for the fields. This is what #pragma pack(n) also does in MSVC. It is also possible to set a minimum alignment for how the subclass itself is packed in the same way #pragma align(n) works in MSVC. This can be achieved by specifying a _align_ class attribute in the subclass definition.

ctypes は Structure と Union に対してネイティブのバイトオーダーを使います。ネイティブではないバイトオーダーの構造体を作成するには、 BigEndianStructure, LittleEndianStructure, BigEndianUnion および LittleEndianUnion ベースクラスの中の一つを使います。これらのクラスにポインタフィールドを持たせることはできません。

構造体と共用体におけるビットフィールド

ビットフィールドを含む構造体や共用体も作成できます。 ビットフィールドにできるのは整数フィールドだけで、ビット幅は _fields_ のタプルの第 3 要素として指定します。

>>> class Int(Structure):
...     _fields_ = [("first_16", c_int, 16),
...                 ("second_16", c_int, 16)]
...
>>> print(Int.first_16)
<Field type=c_long, ofs=0:0, bits=16>
>>> print(Int.second_16)
<Field type=c_long, ofs=0:16, bits=16>
>>>

配列

配列 (Array) はシーケンスであり、決まった数の同じ型のインスタンスを持ちます。

推奨されている配列の作成方法はデータ型に正の整数を掛けることです。:

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 という行が並んだものを表示します。配列の要素がゼロで初期化されているためです。

正しい型の初期化子を指定することもできます。:

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

ポインタ

ポインタのインスタンスは ctypes 型に対して pointer() 関数を呼び出して作成します。:

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

次のように、ポインタインスタンスは、ポインタが指すオブジェクト (上の例では i) を返す contents 属性を持ちます:

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

ctypes は OOR (original object return 、元のオブジェクトを返すこと) ではないことに注意してください。属性を取り出す度に、新しい同等のオブジェクトを作成しているのです。:

>>> 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 関数からポインタを受け取り、そのポインタが単一の要素ではなく実際に配列を指していると 分かっている 場合だけです。

警告

Because pointer objects support subscription, they implicitly support iteration. Unless doing this in a controlled manner, such as by manually calling next() on a pointer() iterator, this will typically lead to infinite loops or crashes, because ctypes has no way of knowing when to stop iteration. In other words, a pointer iterator will infinitely yield arbitrary memory.

舞台裏では、 pointer() 関数は単にポインタインスタンスを作成するという以上のことを行っています。はじめにポインタ 型 を作成する必要があります。これは任意の ctypes 型を受け取る POINTER() 関数を使って行われ、新しい型を返します:

>>> 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 はポインタの指す値を取り出すときに NULL かどうかを調べます(しかし、 NULL でない不正なポインタの指す値の取り出す行為は 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
>>>

型変換

通常、ctypes は厳密な型検査を行います。 例えば、関数の argtypes リストや構造体定義のメンバーフィールドの型に POINTER(c_int) を指定した場合、まったく同じ型のインスタンスしか受け付けません。 ただし、この規則には例外があり、ctypes がほかのオブジェクトを受け付ける場合もあります。 例えば、ポインタ型の代わりに、互換性のある配列インスタンスを渡せます。 そのため、POINTER(c_int) に対しては、ctypes は 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
>>>

さらに、argtypes で関数の引数を POINTER(c_int) などのポインタ型として明示的に宣言した場合、参照先の型 (この場合は c_int) のオブジェクトを関数に渡せます。 この場合、ctypes は必要な byref() 変換を自動的に適用します。

POINTER型フィールドを NULL に設定するために、 None を代入してもかまいません。:

>>> bar.values = None
>>>

時には、非互換な型のインスタンスであることもあります。 C では、ある型を他の型へキャストすることができます。 ctypes は同じやり方で使える cast() 関数を提供しています。上で定義した Bar 構造体は POINTER(c_int) ポインタまたは c_int 配列を values フィールドに対して受け取り、他の型のインスタンスは受け取りません:

>>> 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 では、前方宣言により指定され、後で定義されます。:

struct cell; /* 前方宣言 */

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 は C の呼び出し可能な関数ポインタを Python 呼び出し可能オブジェクトから作成できるようにします。これらは コールバック関数 と呼ばれることがあります。

最初に、コールバック関数のためのクラスを作る必要があります。そのクラスには呼び出し規約、戻り値の型およびこの関数が受け取る引数の数と型についての情報があります。

CFUNCTYPE() ファクトリ関数は通常の cdecl 呼び出し規約を用いてコールバック関数のための型を作成します。 Windows では、 WINFUNCTYPE() ファクトリ関数が stdcall 呼び出し規約を用いてコールバック関数の型を作成します。

これらのファクトリ関数はともに最初の引数に戻り値の型、残りの引数としてコールバック関数が想定する引数の型を渡して呼び出されます。

ここでは、標準 C ライブラリの qsort() 関数を使う例を示します。 この関数は、コールバック関数を使って要素をソートします。 qsort() で整数の配列をソートしてみます。

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

qsort() は、ソートするデータへのポインタ、データ配列の要素数、1 要素のサイズ、比較関数であるコールバックへのポインタを渡して呼び出す必要があります。 コールバックは、要素への 2 つのポインタを引数として呼び出されます。 最初の要素が 2 番目より小さければ負の整数、等しければゼロ、それ以外なら正の整数を返す必要があります。

コールバック関数は整数へのポインタを受け取り、整数を返す必要があります。まず、コールバック関数のための 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
>>>

ここで 2 つの要素を実際に比較し、役に立つ結果を返します:

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

注釈

C コードから CFUNCTYPE() オブジェクトが使用される限り、そのオブジェクトへの参照を確実に保持してください。 ctypes は参照を保持しないため、あなたが参照を保持しないと、オブジェクトはガベージコレクションの対象となり、コールバックが行われたときにプログラムをクラッシュさせる場合があります。

同様に、コールバック関数が Python の管理外 (例えば、コールバックを呼び出す外部のコード) で作られたスレッドで呼び出された場合、 ctypes は全ての呼び出しごとに新しいダミーの Python スレッドを作成することに注意してください。 この動作はほとんどの目的に対して正しいものですが、同じ C スレッドからの呼び出しだったとしても、 threading.local で格納された値は異なるコールバックをまたいで生存は しません 。

dllからエクスポートされた値へアクセスする

共有ライブラリには、関数だけでなく変数もエクスポートするものがあります。 Python ライブラリ自体にも例があり、Py_Version は Python ランタイムのバージョン番号を単一の定数の整数に符号化したものです。

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

ポインタの使い方を説明する拡張例では、 Python がエクスポートする PyImport_FrozenModules ポインタにアクセスします。

この値のドキュメントから引用すると:

このポインタは _frozen のレコードからなり、終端の要素のメンバが NULL かゼロになっているような配列を指すよう初期化されます。 フリーズされたモジュールをインポートするとき、このテーブルを検索します。 サードパーティ製のコードからこのポインタに仕掛けを講じて、動的に生成されたフリーズ化モジュールの集合を提供するようにできます。

これで、このポインタを操作することが役に立つことを証明できるでしょう。例の大きさを制限するために、このテーブルを 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
...                ]
...
>>>

私たちは _frozen データ型を定義済みなので、このテーブルを指すポインタを得ることができます。:

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

table が struct_frozen レコードの配列への pointer なので、その配列に対して反復処理を行えます。しかし、ループが確実に終了するようにする必要があります。なぜなら、ポインタに大きさの情報がないからです。遅かれ早かれ、アクセス違反か何かでクラッシュすることになるでしょう。 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
>>> # 2 つの点を交換します
>>> 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 からインスタンス化されたオブジェクトは、bytes または整数に設定された値しか持てません。

なぜ False と表示されるのでしょうか? ctypes インスタンスはメモリと、メモリの内容にアクセスするいくつかの descriptor (記述子)を含むオブジェクトです。メモリブロックに Python オブジェクトを保存してもオブジェクト自身が保存される訳ではなく、オブジェクトの contents が保存されます。その contents に再アクセスすると新しい Python オブジェクトがその度に作られます。

可変サイズのデータ型

ctypes は可変サイズの配列と構造体をサポートしています。

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

ctypes で可変サイズのデータ型を使うもう一つの方法は、必要なサイズが分かった後に Python の動的性質を使って一つ一つデータ型を(再)定義することです。

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.

共有ライブラリをロードする

共有ライブラリを Python プロセスへロードする方法はいくつかあります。一つの方法は下記のクラスの一つをインスタンス化することです:

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

このクラスのインスタンスはロードされた共有ライブラリをあらわします。これらのライブラリの関数は標準 C 呼び出し規約を使用し、 int を返すと仮定されます。

Windows では、DLL の名前が存在していても CDLL インスタンスの作成が失敗することがあります。 ロードする DLL の依存先 DLL が見つからない場合、"[WinError 126] The specified module could not be found" というメッセージで OSError が送出されます。 Windows API がこの情報を返さないため、エラーメッセージには見つからない DLL の名前が含まれず、原因の特定が難しくなります。 このエラーを解決し、見つからない DLL を特定するには、依存先 DLL の一覧を調べ、Windows のデバッグツールやトレースツールで、どれが見つからないのかを判定する必要があります。

バージョン 3.12 で変更: name 引数に path-like object を指定できるようになりました。

参考

Microsoft DUMPBIN tool -- A tool to find DLL dependents.

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.

バージョン 3.3 で変更: 以前は WindowsError を送出していましたが、現在は OSError の別名になっています。

バージョン 3.12 で変更: name 引数に 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.

バージョン 3.12 で変更: name 引数に path-like object を指定できるようになりました。

これらのライブラリがエクスポートするどの関数でも呼び出す前に Python global interpreter lock は解放され、後でまた獲得されます。

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

Python GIL が関数呼び出しの間解放 されず 、関数実行の後に Python エラーフラグがチェックされるということを除けば、このクラスのインスタンスは CDLL インスタンスのように振る舞います。エラーフラグがセットされた場合、 Python 例外が送出されます。

要するに、これは Python C api 関数を直接呼び出すのに便利だというだけです。

バージョン 3.12 で変更: name 引数に 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 では 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 のプライベートコピーを置き換え、以前の値を返します。

use_last_error 引数を真に設定すると、Windows API 関数の GetLastError() と SetLastError() が管理する Windows エラーコードについて同じ仕組みが有効になります。 ctypes 内部にある Windows エラーコードのコピーの取得と変更には、ctypes.get_last_error() と ctypes.set_last_error() を使います。

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")  # Linux の場合
>>> libc.time == libc.time
True
>>> libc['time'] == libc['time']
False

次に述べる公開属性が利用できます。それらの名前はエクスポートされた関数名に衝突しないように下線で始まります。:

PyDLL._handle

ライブラリへのアクセスに用いられるシステムハンドル。

PyDLL._name

コンストラクタに渡されたライブラリの名前。

あらかじめ作成されている LibraryLoader クラスのインスタンスを使って、共有ライブラリをロードすることもできます。 LoadLibrary() メソッドを呼び出すか、ローダーインスタンスの属性としてライブラリを取得します。

class ctypes.LibraryLoader(dlltype)

共有ライブラリをロードするクラス。 dlltype は CDLL 、 PyDLL 、 WinDLL もしくは OleDLL 型の一つであるべきです。

__getattr__() には特別な動作があります。 ライブラリローダーインスタンスの属性にアクセスすると、共有ライブラリをロードできます。 結果はキャッシュされるため、属性へのアクセスを繰り返しても毎回同じライブラリを返します。

LoadLibrary(name)

共有ライブラリをプロセスへロードし、それを返します。このメソッドはライブラリの新しいインスタンスを常に返します。

これらの前もって作られたライブラリローダーを利用することができます。:

ctypes.cdll

CDLL インスタンスを作ります。

ctypes.windll

WinDLL インスタンスを作成します。

ctypes.oledll

OleDLL インスタンスを作成します。

ctypes.pydll

PyDLL インスタンスを作ります。

C Python api に直接アクセスするために、すぐに使用できる Python 共有ライブラリオブジェクトが次のように用意されています。

ctypes.pythonapi

Python C API 関数を属性として公開する PyDLL のインスタンスです。 すべての関数が C の int を返すと仮定していますが、実際には常にそうとは限りません。 これらの関数を使うには、restype 属性に正しい型を設定する必要があります。

Note that if the Python interpreter is statically linked, this will be None, as dlopen is not possible in this case.

これらのオブジェクトを通じてライブラリをロードすると、ロードに使うライブラリ名を文字列引数 name とする 監査イベント ctypes.dlopen が発生します。

ロード済みライブラリの関数にアクセスすると、引数 library (ライブラリオブジェクト) と name (文字列または整数のシンボル名) を持つ監査イベント ctypes.dlsym が発生します。

ライブラリオブジェクトではなくハンドルだけが利用できる場合、関数にアクセスすると、引数 handle (生のライブラリハンドル) と name を持つ監査イベント ctypes.dlsym/handle が発生します。

外部関数

前の節で説明したとおり、外部関数にはロード済み共有ライブラリの属性としてアクセスできます。 この方法で作成した関数オブジェクトは、デフォルトで任意の数の引数を受け付け、任意の ctypes データインスタンスを引数に取ります。 戻り値の型は、ライブラリローダーが指定するデフォルトの型になります。

これらは、非公開の _CFuncPtr クラスを継承する、非公開のローカルクラス _FuncPtr のインスタンスです (ctypes では公開されていません)。

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

外部関数の結果の型を指定するために ctypes 型を代入する。何も返さない関数を表す void に対しては None を使います。

ctypes の型以外の、Python の呼び出し可能オブジェクトを代入することもできます。 この場合、関数は C の int を返すと仮定され、その整数を渡して呼び出し可能オブジェクトを呼び出すことで、追加の処理やエラー検査を行えます。 この使い方は非推奨です。 より柔軟な後処理やエラー検査を行うには、restype に ctypes のデータ型を設定し、errcheck 属性に呼び出し可能オブジェクトを代入してください。

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.

新機能: argtypes に ctypes の型以外の要素も指定できるようになりました。 ただし、各要素には、引数として使える値 (整数、文字列、ctypes インスタンス) を返す from_param() メソッドが必要です。 これにより、独自のオブジェクトを関数の引数に適合させるアダプターを定義できます。

errcheck

Python 関数または他の呼び出し可能オブジェクトをこの属性に代入します。呼び出し可能オブジェクトは三つ以上の引数とともに呼び出されます。

callable(result, func, arguments)

result は、restype 属性で指定された型で外部関数が返す値です。

func は外部関数オブジェクト自身で、これにより複数の関数の処理結果をチェックまたは後処理するために、同じ呼び出し可能オブジェクトを再利用できるようになります。

arguments は関数呼び出しに最初に渡されたパラメータが入ったタプルです。これにより使われた引数に基づいた特別な振る舞いをさせることができるようになります。

この関数が返すオブジェクトは外部関数呼び出しから返された値でしょう。しかし、戻り値をチェックして、外部関数呼び出しが失敗しているなら例外を送出させることもできます。

exception ctypes.ArgumentError

この例外は外部関数呼び出しが渡された引数を変換できなかったときに送出されます。

Windows では、外部関数呼び出しがアクセス違反などのシステム例外を発生させると、それを捕捉して適切な Python 例外に置き換えます。 さらに、引数 code を持つ監査イベント ctypes.set_exception が発生し、監査フックが独自の例外に置き換えられるようになります。

Some ways to invoke foreign function calls 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 が真に設定されれば、呼び出しの前後で System 変数 errno の ctypesプライベートコピーは本当の errno の値と交換されます。 use_last_error も Windows エラーコードに対するのと同様です。

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

返された関数プロトタイプは、stdcall 呼び出し規約を使う関数を作成します。 関数は呼び出し中に GIL を解放します。 use_errno と use_last_error の意味は上記と同じです。

ctypes.PYFUNCTYPE(restype, *argtypes)

返された関数プロトタイプは Python 呼び出し規約を使う関数を作成します。関数は呼び出されている間 GIL を解放 しません。

ファクトリ関数によって作られた関数プロトタイプは呼び出しのパラメータの型と数に依存した別の方法でインスタンス化することができます。 :

prototype(address)

指定されたアドレス(整数でなくてはなりません)の外部関数を返します。

prototype(callable)

Python の callable から C の呼び出し可能関数(コールバック関数) を作成します。

prototype(func_spec[, paramflags])

共有ライブラリがエクスポートしている外部関数を返します。 func_spec は 2 要素タプル (name_or_ordinal, library) でなければなりません。第一要素はエクスポートされた関数の名前である文字列、またはエクスポートされた関数の序数である小さい整数です。第二要素は共有ライブラリインスタンスです。

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

COM メソッドを呼び出す外部関数を返します。 vtbl_index は仮想関数テーブルのインデックスで、非負の小さい整数です。 name は COM メソッドの名前です。 iid はオプションのインターフェイス識別子へのポインタで、拡張されたエラー情報の提供のために使われます。

COM メソッドは特別な呼び出し規約を使います。 argtypes タプルで指定した引数に加えて、第 1 引数として COM インターフェースへのポインタが必要です。

オプションの paramflags パラメータは上述した機能より多機能な外部関数ラッパーを作成します。

paramflags は、argtypes と同じ長さのタプルでなければなりません。

このタプルの個々の要素はパラメータについてのより詳細な情報を持ち、 1 、 2 もしくは 3 要素を含むタプルでなければなりません。

第一要素はパラメータについてのフラグの組み合わせを含んだ整数です。

1

入力パラメータを関数に指定します。

2

出力パラメータ。外部関数が値を書き込みます。

4

デフォルトで整数ゼロになる入力パラメータ。

オプションの第二要素はパラメータ名の文字列です。これが指定された場合は、外部関数を名前付きパラメータで呼び出すことができます。

オプションの第三要素はこのパラメータのデフォルト値です。

次の例では、Windows の MessageBoxW 関数をラップして、引数のデフォルト値と名前付き引数をサポートする方法を示します。 Windows ヘッダーファイルの C 宣言は次のとおりです。

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

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

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 インスタンスを返します。

出力引数は errcheck プロトコルと組み合わせて、出力の追加処理やエラー検査を行えます。 win32 API の GetWindowRect 関数は成功か失敗かを BOOL で返すので、次の関数でエラーを検査し、API 呼び出しが失敗した場合に例外を送出できます。

>>> 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 (ctypes 型のインスタンスでなければならない) への軽量ポインタを返します。 offset はデフォルトでは 0 で、内部ポインターへ加算される整数です。

byref(obj, offset) は、 C コードとしては、以下のようにみなされます。:

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

返されるオブジェクトは外部関数呼び出しのパラメータとしてのみ使用できます。pointer(obj) と似たふるまいをしますが、作成が非常に速く行えます。

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)

この関数は変更可能な Unicode 文字バッファを作成します。返されるオブジェクトは 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()

この関数は、ctypes でプロセス内 COM サーバーを実装するためのフックです。 _ctypes 拡張 DLL がエクスポートする DllCanUnloadNow() 関数から呼び出されます。

ctypes.DllGetClassObject()

この関数は、ctypes でプロセス内 COM サーバーを実装するためのフックです。 _ctypes 拡張 DLL がエクスポートする DllGetClassObject() 関数から呼び出されます。

ctypes.util.find_library(name)

ライブラリを検索し、パス名を返します。 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 *) で解放する必要があるなら、メモリ割り付けを行ったのと同じライブラリの関数を使うことが重要です。

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.

ctypes.GetLastError()

呼び出し元スレッドで Windows が設定した最後のエラーコードを返します。 Windows の GetLastError() 関数を直接呼び出し、ctypes 内部のエラーコードのコピーは返しません。

ctypes.get_errno()

システムの errno 変数の、スレッドローカルなプライベートコピーを返します。

引数無しで 監査イベント ctypes.get_errno を送出します。

ctypes.get_last_error()

呼び出し元スレッドにある、システムの LastError 変数の ctypes 内部のコピーの現在値を返します。

引数無しで 監査イベント 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 and return a new ctypes pointer type. Pointer types are cached and reused internally, so calling this function repeatedly is cheap. type must be a ctypes type.

ctypes.pointer(obj, /)

obj を指す新しいポインタインスタンスを作成します。 返されるオブジェクトの型は 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)

呼び出し元スレッドにある、システムの LastError 変数の ctypes 内部のコピーの現在値を value に設定し、以前の値を返します。

引数 error を指定して 監査イベント ctypes.set_last_error を送出します。

ctypes.sizeof(obj_or_type)

ctypes の型やインスタンスのメモリバッファのサイズをバイト数で返します。C の sizeof 演算子と同様の動きをします。

ctypes.string_at(ptr, size=-1)

void *ptr にあるバイト文字列を返します。 size を指定した場合はそのサイズを使い、省略した場合はゼロ終端文字列と仮定します。

引数 ptr、size を持つ 監査イベント ctypes.string_at が発生します。

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

This function is probably the worst-named thing in ctypes. It 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.

バージョン 3.3 で変更: 以前は WindowsError のインスタンスを作成していましたが、現在は OSError の別名になっています。

ctypes.wstring_at(ptr, size=-1)

void *ptr にあるワイド文字列を返します。 size を指定した場合は文字数として使い、省略した場合はゼロ終端文字列と仮定します。

引数 ptr、size を持つ 監査イベント ctypes.wstring_at が発生します。

データ型

class ctypes._CData

この非公開クラスはすべての ctypes データ型の共通のベースクラスです。他のことはさておき、すべての ctypes 型インスタンスは C 互換データを保持するメモリブロックを内部に持ちます。このメモリブロックのアドレスは addressof() ヘルパー関数が返します。別のインスタンス変数が _objects として公開されます。これはメモリブロックがポインタを含む場合に存続し続ける必要のある他の Python オブジェクトを含んでいます。

ctypes データ型に共通のメソッドです。 すべてクラスメソッドです (正確には メタクラス のメソッドです):

from_buffer(source[, offset])

このメソッドは source オブジェクトのバッファを共有する ctypes のインスタンスを返します。 source オブジェクトは書き込み可能バッファインターフェースをサポートしている必要があります。オプションの offset 引数では source バッファのオフセットをバイト単位で指定します。デフォルトではゼロです。もし source バッファが十分に大きくなければ、 ValueError が送出されます。

引数 pointer, size, offset を指定して 監査イベント ctypes.cdata/buffer を送出します。

from_buffer_copy(source[, offset])

このメソッドは source オブジェクトの読み出し可能バッファをコピーすることで、ctypes のインスタンスを生成します。オプションの offset 引数では source バッファのオフセットをバイト単位で指定します。デフォルトではゼロです。もし source バッファが十分に大きくなければ、 ValueError が送出されます。

引数 pointer, size, offset を指定して 監査イベント ctypes.cdata/buffer を送出します。

from_address(address)

このメソッドは address で指定されたメモリを使って ctypes 型のインスタンスを返します。 address は整数でなければなりません。

このメソッドと、それを間接的に呼び出すメソッドは、引数 address を持つ 監査イベント ctypes.cdata を発生させます。

from_param(obj)

obj を ctypes の型に適合させるメソッドです。 外部関数の argtypes タプルにその型が含まれている場合、実際の関数呼び出しで使われるオブジェクトを渡して呼び出されます。 関数呼び出しの引数として使えるオブジェクトを返す必要があります。

すべての ctypes のデータ型は、それが型のインスタンスであれば、 obj を返すこのクラスメソッドのデフォルトの実装を持ちます。いくつかの型は、別のオブジェクトも受け付けます。

in_dll(library, name)

このメソッドは、共有ライブラリによってエクスポートされた ctypes 型のインスタンスを返します。 name はエクスポートされたデータの名前で、 library はロードされた共有ライブラリです。

ctypes データ型共通のインスタンス変数:

_b_base_

ctypes 型データのインスタンスは、それ自身のメモリブロックを持たず、基底オブジェクトのメモリブロックの一部を共有することがあります。 _b_base_ 読み出し専用属性は、メモリブロックを保持する ctypes の基底オブジェクトです。

_b_needsfree_

この読み出し専用の変数は、 ctypes データインスタンスが、それ自身に割り当てられたメモリブロックを持つとき true になります。それ以外の場合は false になります。

_objects

このメンバは None 、または、メモリブロックの内容が正しく保つために、生存させておかなくてはならない Python オブジェクトを持つディクショナリです。このオブジェクトはデバッグでのみ使われます。決してディクショナリの内容を変更しないで下さい。

基本データ型

class ctypes._SimpleCData

この非公開クラスは、全ての基本的な ctypes データ型の基底クラスです。 これは基本的な ctypes データ型に共通の属性を持っているので、ここで触れておきます。 _SimpleCData は _CData の子クラスなので、そのメソッドと属性を継承しています。 ポインタそのものではなく、ポインタも含まない ctypes データ型は、現在は pickle 化できます。

インスタンスは一つだけ属性を持ちます:

value

この属性はインスタンスの実際の値を保持します。 整数型とポインタ型では整数、文字型では一文字の bytes オブジェクトまたは文字列、文字へのポインタ型では Python の bytes オブジェクトまたは文字列です。

value 属性が ctypes インスタンスより参照されたとき、大抵の場合はそれぞれに対し新しいオブジェクトを返します。 ctypes はオリジナルのオブジェクトを返す実装にはなって おらず 新しいオブジェクトを構築します。同じことが他の ctypes オブジェクトインスタンスに対しても言えます。

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.

基本データ型のサブクラスは、この動作を継承 しません。 したがって、外部関数の restype が c_void_p のサブクラスの場合、関数呼び出しからそのサブクラスのインスタンスを受け取ります。 もちろん、value 属性にアクセスすればポインタの値を取得できます。

これらが基本 ctypes データ型です:

class ctypes.c_byte

C の signed char データ型を表し、小整数として値を解釈します。コンストラクタはオプションの整数初期化子を受け取ります。オーバーフローのチェックは行われません。

class ctypes.c_char

C char データ型を表し、単一の文字として値を解釈します。コンストラクタはオプションの文字列初期化子を受け取り、その文字列の長さちょうど一文字である必要があります。

class ctypes.c_char_p

C char* データ型を表し、ゼロ終端文字列へのポインタでなければなりません。バイナリデータを指す可能性のある一般的なポインタに対しては POINTER(c_char) を使わなければなりません。コンストラクタは整数のアドレスもしくはバイト列オブジェクトを受け取ります。

class ctypes.c_double

C double データ型を表します。コンストラクタはオプションの浮動小数点数初期化子を受け取ります。

class ctypes.c_longdouble

C long double データ型を表します。コンストラクタはオプションで浮動小数点数初期化子を受け取ります。 sizeof(long double) == sizeof(double) であるプラットフォームでは c_double の別名です。

class ctypes.c_float

C float データ型を表します。コンストラクタはオプションの浮動小数点数初期化子を受け取ります。

class ctypes.c_int

C signed int データ型を表します。コンストラクタはオプションの整数初期化子を受け取ります。オーバーフローのチェックは行われません。 sizeof(int) == sizeof(long) であるプラットフォームでは、 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

C 16-bit signed int データ型を表します。たいていは、 c_short の別名です。

class ctypes.c_int32

C 32-bit signed int データ型を表します。たいていは、 c_int の別名です。

class ctypes.c_int64

C 64-bit signed int データ型を表します。たいていは、 c_longlong の別名です。

class ctypes.c_long

C signed long データ型を表します。コンストラクタはオプションの整数初期化子を受け取ります。オーバーフローのチェックは行われません。

class ctypes.c_longlong

C signed long long データ型を表します。コンストラクタはオプションの整数初期化子を受け取ります。オーバーフローのチェックは行われません。

class ctypes.c_short

C signed short データ型を表します。コンストラクタはオプションの整数初期化子を受け取ります。オーバーフローのチェックは行われません。

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

C の unsigned char データ型を表し、小さな整数として値を解釈します。コンストラクタはオプションの整数初期化子を受け取ります; オーバーフローのチェックは行われません。

class ctypes.c_uint

C の unsigned int データ型を表します。コンストラクタはオプションの整数初期化子を受け取ります; オーバーフローのチェックは行われません。これは、 sizeof(int) == sizeof(long) であるプラットフォームでは 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

C 16-bit unsigned int データ型を表します。たいていは、 c_ushort の別名です。

class ctypes.c_uint32

C 32-bit unsigned int データ型を表します。たいていは、 c_uint の別名です。

class ctypes.c_uint64

C 64-bit unsigned int データ型を表します。たいていは、 c_ulonglong の別名です。

class ctypes.c_ulong

C unsigned long データ型を表します。コンストラクタはオプションの整数初期化子を受け取ります。オーバーフローのチェックは行われません。

class ctypes.c_ulonglong

C unsigned long long データ型を表します。コンストラクタはオプションの整数初期化子を受け取ります。オーバーフローのチェックは行われません。

class ctypes.c_ushort

C unsigned short データ型を表します。コンストラクタはオプションの整数初期化子を受け取ります。オーバーフローのチェックは行われません。

class ctypes.c_void_p

C void* データ型を表します。値は整数として表されます。コンストラクタはオプションの整数初期化子を受け取ります。

class ctypes.c_wchar

C wchar_t データ型を表し、値は Unicode 文字列の単一の文字として解釈されます。コンストラクタはオプションの文字列初期化子を受け取り、その文字列の長さはちょうど一文字である必要があります。

class ctypes.c_wchar_p

C wchar_t* データ型を表し、ゼロ終端ワイド文字列へのポインタでなければなりません。コンストラクタは整数のアドレスもしくは文字列を受け取ります。

class ctypes.c_bool

C の bool データ型 (より正確には、 C99 以降の _Bool) を表します。 True または False の値を持ち、コンストラクタは真偽値と解釈できるオブジェクトを受け取ります。

class ctypes.HRESULT

関数やメソッドの呼び出しの成功またはエラーに関する情報を含む HRESULT 値を表します。

class ctypes.py_object

C PyObject* データ型を表します。引数なしでこれを呼び出すと NULL PyObject* ポインタを作成します。

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)

ネイティブのバイトオーダーでの共用体のための抽象ベースクラス。

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

ビックエンディアン バイトオーダーでの共用体のための抽象ベースクラス。

Added in version 3.11.

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

リトルエンディアン バイトオーダーでの共用体のための抽象ベースクラス。

Added in version 3.11.

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

ビックエンディアン バイトオーダーでの構造体のための抽象ベースクラス。

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

リトルエンディアン バイトオーダーでの構造体のための抽象ベースクラス。

ネイティブではないバイトオーダーを持つ構造体および共用体にポインタ型フィールドあるいはポインタ型フィールドを含む他のどんなデータ型をも入れることはできません。

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

ネイティブ のバイトオーダーでの構造体のための抽象ベースクラス。

具象構造体型と具象共用体型はこれらの型の一つをサブクラス化することで作らなければなりません。少なくとも、 _fields_ クラス変数を定義する必要があります。 ctypes は、属性に直接アクセスしてフィールドを読み書きできるようにする デスクリプタ を作成するでしょう。これらは、

_fields_

構造体のフィールドを定義するシーケンス。要素は2要素タプルか3要素タプルでなければなりません。第一要素はフィールドの名前です。第二要素はフィールドの型を指定します。それはどんな ctypes データ型でも構いません。

c_int のような整数型のために、オプションの第三要素を与えることができます。フィールドのビット幅を定義する正の小整数である必要があります。

一つの構造体と共用体の中で、フィールド名はただ一つである必要があります。これはチェックされません。名前が繰り返しでてきたときにアクセスできるのは一つのフィールドだけです。

Structure サブクラスを定義するクラス文の 後で 、 _fields_ クラス変数を定義することができます。これにより、次のように自身を直接または間接的に参照するデータ型を作成できるようになります:

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

The _fields_ class variable must, however, be defined before the type is first used (an instance is created, sizeof() is called on it, and so on). Later assignments to the _fields_ class variable will raise an AttributeError.

It is possible to define sub-subclasses of structure types, they 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. _pack_ must already be defined when _fields_ is assigned, otherwise it will have no effect. Setting this attribute to 0 is the same as not setting it at all.

_align_

An optional small integer that allows overriding the alignment of the structure when being packed or unpacked to/from memory. Setting this attribute to 0 is the same as not setting it at all.

Added in version 3.13.

_anonymous_

無名 (匿名) フィールドの名前が並べあげられたオプションのシーケンス。 _fields_ が代入されたとき、 _anonymous_ がすでに定義されていなければなりません。そうでなければ、何ら影響はありません。

この変数に並べあげられたフィールドは構造体型もしくは共用体型フィールドである必要があります。構造体フィールドまたは共用体フィールドを作る必要なく、入れ子になったフィールドに直接アクセスできるようにするために、 ctypes は構造体型の中に記述子を作成します。

型の例です (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.Array(*args)

配列のための抽象基底クラスです。

具象配列型を作成するための推奨される方法は、任意の ctypes データ型に非負の整数を乗算することです。代わりに、この型のサブクラスを作成し、 _length_ と _type_ のクラス変数を定義することもできます。配列の要素は、標準の添え字とスライスによるアクセスを使用して読み書きを行うことができます。スライスの読み込みでは、結果のオブジェクト自体は Array ではありません。

Arrays are generic over the type of their elements.

_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

ポインタが指すオブジェクトを返します。この属性に割り当てると、ポインタが割り当てられたオブジェクトを指すようになります。