###
10 構造体と共用体

構造体と共用体は`ctypes`モジュールに定義されている`Structure`および`Union` ベースクラスから導出されなければなりません。それぞれのサブクラスは`_fields_`属性を 定義する必要があります。`_fields_`はフィールド名とフィールド型を持つ 2要素タプルのリストでなければなりません。

フィールド型は`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 ?
    ValueError: too many initializers
    >>>

また、さらに複雑な構造体を構成することができます。Structureはそれ自体が フィールド型に構造体を使うことで他の構造体を内部に持つことができます。

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

フィールド記述子はクラスから取り出せます。デバッグするときに役に立つ情報を 得ることができます:

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