たいていの場合、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 >>>
POINTER型フィールドをNULL
に設定するために、None
を代入してもよい:
>>> bar.values = None >>>
XXX list other conversions...
時には、非互換な型のインスタンスであることもあります。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 ? 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 >>>
ご意見やご指摘をお寄せになりたい方は、 このドキュメントについて... をご覧ください。