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

时间:2016-05-24 21:45:28

标签: python ctypes cpython

这是我已经被困了一段时间了,所以任何输入都会受到赞赏。

运行python 2.7(cpython),考虑以下代表SCSI通用IO结构的ctypes.Structure:

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)]

如果我使用上面的类实例化一个对象,我倾向于观察到ctypes.addressof()返回的内容是否接近通过调用对象上的id()返回的内容:

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

我知道id()和ctypes.addressof()之间应该有一个delta,对应于引用计数和对象识别所需的元数据。我不明白为什么对象的python地址离支持结构的内存地址这么远?

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

1 个答案:

答案 0 :(得分:0)

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

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