2013-08-06 3 views
2

Я пытаюсь распаковать C-структуру, которая передается моей программе Python в двоичной форме и включает в себя еще одну вложенную структуру. Соответствующая часть заголовка C выглядит следующим образом:Распаковка вложенных C-структур в Python

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) 

Однако это, по-видимому, не правильно; строка формата имеет из 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) 
Смежные вопросы