###
15 型変換

たいていの場合、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
    >>>