You need to enable JavaScript to run this app. 如何获取Python ctypes结构体成员类型大小以格式化十六进制输出?
优惠活动
大模型
产品
解决方案
定价
更多

如何获取Python ctypes结构体成员类型大小以格式化十六进制输出?

问题根因定位

你之前调用sizeof报错的核心原因是字段解包逻辑存在偏差:

  • ctypes结构体的_fields_属性中,每个字段条目的固定格式为:普通字段是(字段名称, 类型类)的二元组,带位域的字段是(字段名称, 类型类, 位宽)的三元组。
  • 你写的for name, *dtype in self._fields_:语法,会把条目里第二个及之后的所有元素打包成元组赋值给dtype。比如遇到('a', c_uint16)这样的普通字段时,dtype拿到的是包含类型对象的元组(c_uint16,),并不是类型类本身。把元组传入sizeof方法,自然会触发this type has no size的报错。
修正实现方案
  1. 遍历字段时,直接从每个字段条目的固定索引位置取出对应的类型类对象,再传入sizeof计算实际占用字节数。
  2. 十六进制格式化时,按照1字节对应2个十六进制字符的规则计算输出宽度,通过f-string的动态宽度参数自动补全前导零。

修改后的可直接运行的完整代码如下:

from ctypes import *
class Tracerec(BigEndianStructure):
    def __repr__(self):
        textlist = list()
        for field_entry in self._fields_:
            name = field_entry[0]
            field_type = field_entry[1]
            # 直接取类型对象计算大小,不会触发报错
            byte_size = sizeof(field_type)
            value = getattr(self, name)
            if isinstance(value, int):
                # 每个字节对应2位十六进制,计算需要的总输出宽度
                hex_format_width = byte_size * 2
                textlist.append(f'{name}:0x{value:0{hex_format_width}x}')
            else:
                textlist.append(f'{name}:{value}')
        fulltext = ' '.join(textlist)
        return f'<{self.__class__.__name__}={fulltext}>'
    def __getitem__(self, i):
        if type(i)==str: return getattr(self, i)
        return getattr(self, self._fields_[i][0])
    def __len__(self):
        return len(self._fields_)

class Mystruct(Tracerec):
    _fields_ = [
        ('a', c_uint16),
        ('b', c_uint16),
        ('c', c_uint32),
    ]

buffer = b'\x01\x02\x03\x04\x00\x00\x05\x06'
x = Mystruct.from_buffer_copy(buffer)
print(x)

运行后输出完全匹配预期:

<Mystruct=a:0x0102 b:0x0304 c:0x00000506>

补充说明:哪怕是带位域的字段条目,比如定义('flag', c_uint8, 3),上述逻辑依然可以正确计算类型大小并完成格式化,和常规的结构体打印逻辑保持一致。


内容的提问来源于stack exchange,提问作者mrkbutty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.05 21:45:03