为什么 ctypes.addressof() 与 ctypes.Structure 对象的 id() 不匹配?

Why does ctypes.addressof() not match id() for ctypes.Structure objects?

这是我已经困扰了一段时间的问题,所以任何意见都将不胜感激。

运行 python 2.7 (cpython),考虑下面的ctypes.Structure表示一个SCSI通用IO结构:

import ctypes
class SGIOHeader(ctypes.Structure):
    _fields_ = [
        ('interface_id', ctypes.c_int),
        ('dxfer_direction', ctypes.c_int),
        ('cmd_len', ctypes.c_ubyte),
        ('mx_sb_len', ctypes.c_ubyte),
        ('iovec_count', ctypes.c_ushort),
        ('dxfer_len', ctypes.c_uint),
        ('dxferp', ctypes.c_void_p),
        ('cmdp', ctypes.c_void_p),
        ('sbp', ctypes.c_void_p),
        ('timeout', ctypes.c_uint),
        ('flags', ctypes.c_uint),
        ('pack_id', ctypes.c_int),
        ('usr_ptr', ctypes.c_void_p),
        ('status', ctypes.c_ubyte),
        ('masked_status', ctypes.c_ubyte),
        ('msg_status', ctypes.c_ubyte),
        ('sb_len_wr', ctypes.c_ubyte),
        ('host_status', ctypes.c_ushort),
        ('driver_status', ctypes.c_ushort),
        ('resid', ctypes.c_int),
        ('duration', ctypes.c_uint),
        ('info', ctypes.c_uint)]

如果我使用上述 class 实例化一个对象,我倾向于观察到 ctypes.addressof() 返回的内容与通过调用对象上的 id() 返回的内容相去甚远:

>>> sgio = SGIOHeader()
>>> hex(id(sgio))
'0x10eb5ed40'
>>> hex(ctypes.addressof(sgio))
'0x7fdeca700130'

我理解在 id() 和 ctypes.addressof() 之间应该有一个增量,对应于引用计数和对象识别所需的元数据。我不明白的是为什么对象的 python 地址与支持结构的内存地址相距如此之远?

这是一个问题的原因是,如果我尝试使用 ctypes.addressof() 值发出 ioctl,我将始终得到 EFAULT,因为该对象被认为在我的进程地址之外space。如果对象存在于堆中,它的后备地址怎么会与其身份相距如此之远呢?关于 python 对象在内存中的布局方式,我有什么误解?是否有不同的寻址方案(似乎我得到的是 32 位或 64 位值)?

因为建模的 C 结构和代理它的 Python 对象是两个不同的概念。

id() 为您提供 Python 代理对象的内存地址,ctypes.addressof() 为您提供实际 C 结构的地址。您不能将 Python 对象传递给其他 C 代码,但您 可以 将 C 结构传递给其他 C 代码。