Unpacking nested C structures in Python

I am trying to unpack a C structure that is passed to my Python program in binary form and includes another nested structure. The corresponding part of the C header looks like this:

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; 

Now, in my Python program, I want to use struct.unpack to unpack accpacket . However, I do not know what the format string for unpacking should be like accpacket contains a nested mps_packet_header . I tried to just insert the format string for mps_packet_header at the beginning, and then continue with the rest of accpacket :

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

However, this is apparently not true; The format string has a calcsize of 44, and the structure itself has a size of 54.

How to formulate the correct format string for this structure?

+2
source share
2 answers
  • Struct format Struct not match structure C. (final H must be 6H )
  • struct.unpack ( 6H , ..) returns 6 fields. (not one with 6 elements)

So your code should look like this.

 s = struct.Struct('= BBHH 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:] 
+2
source

You can try building 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) 
+2
source

Source: https://habr.com/ru/post/1200752/


All Articles