为什么 ctypes.c_int 在放入 ctypes 结构时会完全改变其行为?
Why does ctypes.c_int completely change its behaviour when put into ctypes Structure?
当我创建类型为 ctype.c_int
的变量时,它报告该类型并且不允许任何数学运算:
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
另一方面:当我创建一个内部带有 c_int
的结构时,它被报告为 int
,允许数学运算,但似乎仍然存储为 32 位 c 整数,因为它在 32 位上正确换行,并在位置 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!
有人可以解释这种行为吗?这背后有什么逻辑吗?
裸c_int
必须有两个身份:addressof
可能被占用的C对象,Python对象x
。前者是一个整数,而后者不是。 (回想一下 x=2
只会重新绑定 x
而不会更新 C 整数。)
当您将变量放入结构中时,ctypes
可以提供一个 便利 ,一个 attribute-based 在 C 和 Python表示。这有它自己的惊喜:存储一个适当大的值,然后你会看到 rec.x is not rec.x
。制造的对象是真实的 Python 对象,但它们当然不遵循 Python 规则 ,因为它们不拥有任何数据。
这同样适用于裸整数的 value
属性。
奇怪的是,它 相当于结构中的裸整数,因此您不能轻易地将结构成员传递给函数来填充它。
当我创建类型为 ctype.c_int
的变量时,它报告该类型并且不允许任何数学运算:
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
另一方面:当我创建一个内部带有 c_int
的结构时,它被报告为 int
,允许数学运算,但似乎仍然存储为 32 位 c 整数,因为它在 32 位上正确换行,并在位置 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!
有人可以解释这种行为吗?这背后有什么逻辑吗?
裸c_int
必须有两个身份:addressof
可能被占用的C对象,Python对象x
。前者是一个整数,而后者不是。 (回想一下 x=2
只会重新绑定 x
而不会更新 C 整数。)
当您将变量放入结构中时,ctypes
可以提供一个 便利 ,一个 attribute-based 在 C 和 Python表示。这有它自己的惊喜:存储一个适当大的值,然后你会看到 rec.x is not rec.x
。制造的对象是真实的 Python 对象,但它们当然不遵循 Python 规则 ,因为它们不拥有任何数据。
这同样适用于裸整数的 value
属性。
奇怪的是,它