【问题标题】:Unpacking nested C structs in Python在 Python 中解包嵌套的 C 结构
【发布时间】:2013-08-07 13:54:44
【问题描述】:

我正在尝试解压缩以二进制形式传递给我的 Python 程序并包含另一个嵌套结构的 C 结构。 C 标头的相关部分如下所示:

typedef struct {
    uint8_t seq;
    uint8_t type;
    uint16_t flags;
    uint16_t upTimestamp;
}__attribute__ ((packed)) mps_packet_header;

typedef struct {
    mps_packet_header header;
    int16_t x[6];
    int16_t y[6];
    int16_t z[6];
    uint16_t lowTimestamp[6];
}__attribute__((packed)) mps_acc_packet_t;
typedef mps_acc_packet_t accpacket_t;

现在,在我的 Python 程序中,我想使用 struct.unpack 解压缩 accpacket。但是,我不知道解包的格式字符串应该是什么,因为accpacket 包含嵌套的mps_packet_header。我尝试在开头插入mps_packet_header 的格式字符串,然后继续使用accpacket 的其余部分:

s = struct.Struct('= B B H H 6h 6h 6h H')
seq, _type, flags, upTimestamp, x, y, z, lowTimestamp = s.unpack(packet_data)

但是,这显然是不正确的;格式字符串的 calcsize 为 44,而结构本身的大小为 54。

如何为这个结构制定正确的格式字符串?

【问题讨论】:

    标签: python struct nested unpack


    【解决方案1】:
    1. 您的Struct 格式与C 结构不匹配。 (最终的H 应该是6H
    2. struct.unpack(6h, ..) 确实返回 6 个字段。 (不是一个有 6 个元素的)

    所以你的代码应该看起来像..

    s = struct.Struct('= B B H H 6h 6h 6h 6H')
    fields = s.unpack(packet_data)
    seq, _type, flags, upTimestamp = fields[:4]
    x = fields[4:10]
    y = fields[10:16]
    z = fields[16:22]
    lowTimestamp = fields[22:]
    

    【讨论】:

    • 好收获;我错过了最后的量词。有了这个,.size 给出 54。
    【解决方案2】:

    你可以尝试构造http://construct.readthedocs.io/en/latest/

    import construct as cstruct
    def mps_packet_header(name):
        return cstruct.Struct(
            name,
            cstruct.UNInt8('seq'),
            cstruct.UNInt8('type'),
            cstruct.UNInt16('flags'),
            cstruct.UNInt16('upTimestamp'),
        )
    
    mps_acc_packet_t = cstruct.Struct(
        'mps_acc_packet_t',
        mps_packet_header('header')
        cstruct.Array(6, cstruct.NInt16('x')),
        cstruct.Array(6, cstruct.NInt16('y')),
        cstruct.Array(6, cstruct.NInt16('z')),
        cstruct.Array(6, cstruct.UNInt16('lowTimestamp')),
    )
    
    accpacket_t = mps_acc_packet_t
    ...
    ...
    packet_data = ....
    packet = accpacket_t.parse(packet_data)
    print(packet)
    print(packet.header)
    print(packet.x, packet.y, packet.z)
    

    【讨论】:

      猜你喜欢
      • 2013-09-15
      • 2017-10-16
      • 1970-01-01
      • 1970-01-01
      • 2020-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多