I'm writing a Python application that will write a binary file. This file will be parsed by some C code running on an embedded target.
I'm confident that I could do this by deriving from the Struct class, but the packing formatting is awful, and all my struct as little-endian anyways, so I thought of using the ctypes package.
Let's say that I have the following C structure:
struct my_c_struct
{
uint32_t a;
uint16_t b;
uint16_t table[];
};
On the C side, I operate on that structure using a pointer cast to a memory buffer, so I can do:
uint8_t buf[128];
struct my_c_struct *p = (struct my_c_struct*) buf;
p->table[0] = 0xBEEF;
How to best represent this in Python? My first go at it is:
class MyCStruct(ctypes.LittleEndianStructure):
c_uint32 = ctypes.c_uint32
c_uint16 = ctypes.c_uint16
_pack_ = 1
_fields_ = [
("a", c_uint32),
("b", c_uint16),
]
def __init__(self, a, b):
"""
Constructor
"""
super(ctypes.LittleEndianStructure, self).__init__(a, b)
self.table = []
def pack(self):
data = bytearray(self.table)
return bytearray(self)+data
The idea behind the pack()
method is that it'll assemble the variable-length table at the end of the structure. Mind that I don't know how many entries table
has at object creation.
The way I implemented it obviously doesn't work. So I was thinking about nesting the ctypes-devived class in a pure Python class:
class MyCStruct:
class my_c_struct(ctypes.LittleEndianStructure):
_pack_ = 1
_fields_ = [ ("a", ctypes.c_uint32),
("b", ctypes.c_uint16) ]
def __init__(self, a, b):
"""
Constructor
"""
self.c_struct = self.my_c_struct(a,b)
self.table = []
def pack(self):
self.c_struct.b = len(self.table)
x = bytearray(self.c_struct)
y = bytearray()
for v in self._crc_table:
y += struct.pack("<H", v)
return x + y
Is this a good way of doing this? I don't want to go too deep down the rabbit hole just to find out that there was a better way of doing it.
Caveat: I'm working with Python 2 (please don't ask...), so a Python 3-only solution wouldn't be useful for me, but would be useful for the rest of the universe.
Cheers!