6

I am trying to unpack a C struct that is handed to my Python program in binary form and includes another nested struct. The relevant 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 an accpacket. However, I don't know what the format string for the unpack should be as the accpacket contains a nested mps_packet_header. I have tried just inserting the format string for the mps_packet_header at the beginning and then continuing with the rest of the accpacket:

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

However, this is apparently not correct; the format string has a calcsize of 44, while the struct itself has a size of 54.

How do I formulate a correct format string for this struct?

0

2 Answers 2

4
  1. You Struct format does not match with C structure. (final H should be 6H)
  2. struct.unpack(6h, ..) does return 6 fields. (not one with 6 elements)

So your code should looks like ..

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:]
Sign up to request clarification or add additional context in comments.

1 Comment

Good catch; I missed the final quantifier. With that in place the .size gives 54.
4

You can try construct 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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.