You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用ctypes转换字节串至VIDEO_IMAGE_STRUCT结构体结果不符,求排查

排查ctypes大端结构体转换错误

问题说明

使用Python的ctypes库将字节串转换为指定的大端无对齐C结构体时,magic_number和version字段解析结果与预期不符,需排查错误原因。

文档定义的结构体

// VIDEO_IMAGE_STRUCT:大端字节序、无对齐
struct {
    unsigned int     magic_number = 0x5644454f; // 预期值:1447314767
    unsigned short   version;        // 仅支持版本1
    unsigned short   image_mode;     // Y8,Y16等格式
    long     long    frame_number;   // 帧计数(64位)
    int              width;          // 帧宽度(像素)
    int              height;         // 帧高度(像素)
    unsigned short   endianness;     // 0=小端,1=大端
    unsigned short   header_size;    // 头部字节长度
    unsigned short   padding[2];     // 4字节填充(共两个ushort)
} VIDEO_IMAGE_STRUCT;

错误代码

from ctypes import BigEndianStructure, c_int, c_uint, c_ushort, c_long, c_byte

class VideoImageData(BigEndianStructure):
    _pack_ = 1
    _fields_ = [
        ("magic_number", c_uint),
        ("version", c_ushort),
        ("image_mode", c_ushort),
        ("frame_number", c_long),  # 错误:对应文档的long long,应该用c_longlong
        ("width", c_int),
        ("heigth", c_int),         # 拼写错误:应为height
        ("endianness", c_ushort),
        ("header_size", c_ushort),
        ("padding", c_ushort)      # 错误:文档是padding[2],应该定义为(c_ushort * 2)
    ]

if __name__ == "__main__":
    dstr = b'YATD\x02\x00@\x00\x02\x00\x00\x00\x01\x00\x00\x00\x00\x00\x02\x00\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00'
    s = VideoImageData.from_buffer(bytearray(dstr))

异常结果

IN[1]: s.magic_number
Out[1]: 1497453636 (预期值:1447314767)
In[2]: s.version
Out[2]: 512 (预期值:1)

错误原因与修复方案

1. 核心字段类型错误

文档中frame_number是64位长整型(long long),但代码中使用了c_long(对应C的long,通常为32位4字节),导致后续所有字段的偏移量整体错位,这是解析结果不符的主要原因。

  • 修复:将frame_number的类型改为c_longlong。

2. padding字段定义错误

文档中padding是unsigned short[2](两个无符号短整型,共4字节),但代码中只定义了单个c_ushort,结构体总长度计算错误,进一步加剧字段偏移。

  • 修复:将padding定义为(c_ushort * 2)。

3. 变量名拼写错误

代码中heigth应为height,虽然不影响解析,但建议修正以保持与文档一致。

4. 输入字节串的字节顺序问题

输入字节串的前4字节是b'YATD'(十六进制0x59415444),解析为大端无符号整数得到1497453636,但预期的magic_number是0x5644454F(对应字节b'VEDO')。如果确认输入字节串来源正确,需检查数据来源的字节序是否符合文档要求。

修复后的代码

from ctypes import BigEndianStructure, c_int, c_uint, c_ushort, c_longlong

class VideoImageData(BigEndianStructure):
    _pack_ = 1
    _fields_ = [
        ("magic_number", c_uint),
        ("version", c_ushort),
        ("image_mode", c_ushort),
        ("frame_number", c_longlong),
        ("width", c_int),
        ("height", c_int),
        ("endianness", c_ushort),
        ("header_size", c_ushort),
        ("padding", c_ushort * 2)
    ]

if __name__ == "__main__":
    # 替换前4字节为预期的magic_number对应字节,version字段改为00 01
    dstr = b'VEDO\x00\x01@\x00\x02\x00\x00\x00\x01\x00\x00\x00\x00\x00\x02\x00\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00'
    s = VideoImageData.from_buffer(bytearray(dstr))
    
    print(f"magic_number: {s.magic_number} (预期:1447314767)")
    print(f"version: {s.version} (预期:1)")

修复后的验证

修正后的结构体总长度为32字节,与文档定义一致;若输入字节串的前6字节为b'VEDO\x00\x01',解析后magic_number将为1447314767,version为1,符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 18:45:46