###
19 予期しないこと

`ctypes`には別のことを期待しているのに実際に起きる起きることは違うという場合が あります。

次に示す例について考えてみてください:

    >>> 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 = "abc def ghi"
    >>> s.value
    'abc def ghi'
    >>> s.value is s.value
    False
    >>>

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