When I create a variable of type ctype.c_int it reports that type and does not allow any math operations:
In [107]: x = c_int(1)
In [108]: x
Out[108]: c_int(1)
In [109]: x+=1
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
----> 1 x+=1
TypeError: unsupported operand type(s) for +=: 'c_int' and 'int'
In [110]: x+=x
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
----> 1 x+=x
TypeError: unsupported operand type(s) for +=: 'c_int' and 'c_int'
In [111]: type(x)
Out[111]: ctypes.c_int
On the other hand: when I make a structure with c_int inside it is reported as int, allows math operations but still seems to be stored as 32-bit c-integer because it wraps correctly on 32 bit, and honors sign bit at position 31.
In [112]: class REC(ctypes.Structure): _fields_=[('x',ctypes.c_int),('y',ctypes.c_int)]
In [113]: rec = REC()
In [114]: rec.x
Out[114]: 0
In [114]: type(rec.x)
Out[114]: int # why not ctypes.c_int ???
In [116]: rec.x+=0x7FFFFFFF # += works, so it is regular python int ?
In [117]: rec.x
Out[117]: 2147483647
In [118]: rec.x+=1
In [119]: rec.x
Out[119]: -2147483648 # but it honors sign bit at position 31...
In [122]: rec.x=0xFFFFFFFF
In [123]: rec.x
Out[123]: -1
In [124]: rec.x+=1
In [125]: rec.x
Out[125]: 0 # ...and it wraps on 32 bits, so it is NOT python int!
Can someone explain this behavior? Is there any logic behind this?
The bare c_int has to have two identities: the C object whose addressof may be taken, and the Python object x. The former is an integer, but the latter is not. (Recall that x=2 would just rebind x and would not update the C integer.)
When you put the variable in a structure, ctypes can provide, as a convenience, an attribute-based interface that converts between the C and Python representations. This has its own surprises: store a suitably large value and you’ll see that then rec.x is not rec.x. The manufactured objects are real Python objects, but of course they don’t follow Python rules since they don’t own any data.
The same applies to the bare integer’s value attribute.
Oddly enough, it’s hard to get the equivalent of a bare integer from a structure, so you can’t easily pass a structure member to a function to fill it in.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With