Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Handling structs containing arrays with the struct module

While the struct module makes handling C-like structures containing scalar values very simple, I don’t see how to sensibly handle structs which contain arrays.

For example, if I have the following C struct:

struct my_struct {
    int a1[6];
    double a2[3];
    double d1;
    double d2;
    int i1;
    int i2;
    int a3[6];
    int i3;
};

and want to unpack its values and use the same variables (a1, a2, a3, d1, d2, i1, i2, i3) in Python, I run into the problem that struct just gives me every value in a tuple individually. All information about which values are supposed to be grouped in an array is lost:

# doesn’t work!
a1, a2, d1, d2, i1, i2, a3, i3 = struct.unpack(
    '6i3dddii6ii', b'abcdefghijklmnopqrstuvwxy' * 4
)

Instead, I have to slice and pull apart the tuple manually, which is a very tedious and error-prone procedure:

t = struct.unpack('6i3dddii6ii', b'abcdefghijklmnopqrstuvwxy' * 4)
a1 = t[:6]
a2 = t[6:9]
d1, d2, i1, i2 = t[9:13]
a3 = t[13:19]
i3 = t[19]

Is there any better way of handling arrays with struct?

like image 559
Socob Avatar asked Apr 23 '26 18:04

Socob


1 Answers

You can use construct library, which is pretty much wraps struct module and makes parsing and building binary data more convenient.

Here is a basic example:

import construct

my_struct = construct.Struct(
    "a1" / construct.Array(6, construct.Int32sl),
    "a2" / construct.Array(3, construct.Float64l),
    "d1" / construct.Float64l,
    "d2" / construct.Float64l,
    "i1" / construct.Int32sl,
    "i2" / construct.Int32sl,
    "a3" / construct.Array(6, construct.Int32sl),
    "i3" / construct.Int32sl
)



parsed_result = my_struct.parse(b'abcdefghijklmnopqrstuvwxy' * 4)

# now all struct attributes are available
print(parsed_result.a1)
print(parsed_result.a2)
print(parsed_result.i3)


assert 'a1' in parsed_result
assert 'i3' in parsed_result
like image 166
Alex Avatar answered Apr 25 '26 07:04

Alex



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!