int 的 ctypes.c_int 和 ctypes.py_object 之间的区别

问题描述 投票:0回答:1

我在 CPython 上使用 Python 3.9.6。

我试图理解 PyObject 和 c_int 对于数字的内部表示的差异。

>>> x = 1234
>>> c1 = c_int(x)
>>> id(c1)
4339302720
>>> type(c1)
<class 'ctypes.c_int'>
>>> c1.value
1234
>>> cast(addressof(c1),POINTER(c_int)).contents.value
1234
>>>

这里,c1本身就是一个PyObject,它的地址是4339302720。它代表一个ctypes.c_int对象,这个addressof(c1)应该指向存储int值的内存位置。当该地址被解释为 int 并且其值被转储时,这一点得到确认。我假设 c1.value 在内部做同样的事情。

2.


>>> c2 = cast(id(x),py_object)
>>> id(c2)
4337584448
>>> type(c2)
<class 'ctypes.py_object'>
>>> c2.value
1234
>>> cast(addressof(c2),POINTER(c_int)).contents.value
43544656

这里,c2也是一个PyObject,其地址为4337584448。它是否代表另一个ctypes.py_object对象?

由于这是一个ctypes对象,因此它支持addressof(c2)。

addressof(c2) 指向什么,因为它不指向整数 1234?您还可以补充您的答案,指出一个很好的参考资料,以便我可以从“第一原则”中理解吗?

另外,c2.value 内部如何计算为 1234?

python python-3.x ctypes pyobject
1个回答
0
投票

ctypes.addressof
ctypes.c_int
是存储C整数的4个字节的地址。

>>> from ctypes import *
>>> x = 1234
>>> a = c_uint(x)
>>> hex(addressof(a))  # int*
'0x231c2135498'
>>> string_at(addressof(a),4).hex()  # little-endian 4-byte integer
'd2040000'
>>> 0x04d2  # byte-swapped and converted to int
1234

ctypes.addressof
ctypes.py_object
是存储对象引用的
PyObject*
的8个字节的地址。这就是为什么在第二种情况下你会得到一个奇怪的数字。

>>> from ctypes import *
>>> x = 1234
>>> y = py_object(x)
>>> hex(addressof(y))  # PyObject*
'0x231c2135498'
>>> string_at(addressof(y),8).hex()  # little-endian 8-byte pointer (64-bit OS)
'300713c231020000'  # note lower bytes of this matches the "bad" value of cast below.
>>> hex(id(x))  # In CPython id(x) is the PyObject* address of x.
'0x231c2130730'

如果 PyObject* 被视为 C int* :

>>> cast(addressof(y), POINTER(c_int)).contents
c_long(-1038940368)
>>> import struct
>>> struct.pack('<l',-1038940368).hex() # convert to little-endian 4-byte integer
'300713c2'  # See that it the lower 4 bytes of the little-endian 8-byte PyObject*.

py_object(1234)
的值永远不会与
c_int
值匹配,因为它一开始就不是
c_int
包装的值。但你可以将它作为 Python 对象获取:

>>> x=1234
>>> y=cast(id(x),py_object)  # better, just y=py_object(x)
>>> y
py_object(1234)
>>> y.value
1234
© www.soinside.com 2019 - 2024. All rights reserved.