2013-08-06 89 views
2

我想解壓一個C結構,以二進制形式交給我的Python程序,幷包含另一個嵌套結構。 C頭的相關部分看起來是這樣的:在Python中解壓縮嵌套的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.

如何爲此結構制定正確的格式字符串?

回答

2
  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:] 
+0

良好的漁獲物;我錯過了最後的量詞。隨着那個''.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)