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
>>> temp0, temp1 = rc.b, rc.a >>> rc.a = temp0 >>> rc.b = temp1 >>>
temp1 are objects still using the internal
buffer of the
rc object above. So executing
rc.a = temp0
copies the buffer contents of
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!
See About this document... for information on suggesting changes.