14.14.1.19 Surprises
There are some edges in ctypes where you may be expect something
else than what actually happens.
Consider the following example:
>>> 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
>>>
Hm. We certainly expected the last statement to print 3 4 1 2 .
What happended? Here are the steps of the rc.a, rc.b = rc.b, rc.a
line above:
>>> temp0, temp1 = rc.b, rc.a
>>> rc.a = temp0
>>> rc.b = temp1
>>>
Note that temp0 and temp1 are objects still using the internal
buffer of the rc object above. So executing rc.a = temp0
copies the buffer contents of temp0 into rc 's buffer. This,
in turn, changes the contents of temp1 . So, the last assignment
rc.b = temp1 , doesn't have the expected effect.
Keep in mind that retrieving subobjects from Structure, Unions, and
Arrays doesn't copy the subobject, instead it retrieves a wrapper
object accessing the root-object's underlying buffer.
Another example that may behave different from what one would expect is this:
>>> s = c_char_p()
>>> s.value = "abc def ghi"
>>> s.value
'abc def ghi'
>>> s.value is s.value
False
>>>
Why is it printing False ? ctypes instances are objects containing
a memory block plus some descriptors accessing the contents of the
memory. Storing a Python object in the memory block does not store
the object itself, instead the contents of the object is stored.
Accessing the contents again constructs a new Python each time!
Release 2.5.2, documentation updated on 21st February, 2008.
See About this document... for information on suggesting changes.
|