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

temp0temp1は前記の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オブジェクトがその度に作られます。

ご意見やご指摘をお寄せになりたい方は、 このドキュメントについて... をご覧ください。