Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python ctypesgen/ctypes: How to write struct fields to file in single byte alignment

Using ctypesgen, I generated a struct (let's call it mystruct) with fields defined like so:

[('somelong', ctypes.c_long),
 ('somebyte', ctypes.c_ubyte)
 ('anotherlong', ctypes.c_long),
 ('somestring', foo.c_char_Array_5),
 ]

When I tried to write out an instance of that struct (let's call it x) to file: open(r'rawbytes', 'wb').write(mymodule.mystruct(1, 2, 3, '12345')), I notice that the contents written to the file are not byte-aligned.

How should I write out that struct to file such that the byte-alignment is 1 byte?

like image 539
moog Avatar asked Oct 15 '25 09:10

moog


1 Answers

Define _pack_=1 before defining _fields_.

Example:

import ctypes as ct

def dump(t):
    print(bytes(t).hex())

class Test(ct.Structure):
    _fields_ = (('long', ct.c_long),
                ('byte', ct.c_ubyte),
                ('long2', ct.c_long),
                ('str', ct.c_char * 5))

class Test2(ct.Structure):
    _pack_ = 1
    _fields_ = (('long', ct.c_long),
                ('byte', ct.c_ubyte),
                ('long2', ct.c_long),
                ('str', ct.c_char * 5))

dump(Test(1, 2, 3, b'12345'))
dump(Test2(1, 2, 3, b'12345'))

Output:

0100000002000000030000003132333435000000
0100000002030000003132333435

Alternatively, use the struct module. Note it is important to define the endianness < which outputs the equivalent of _pack_=1. Without it, it will use default packing.

import struct
print(struct.pack('<LBL5s', 1, 2, 3, b'12345').hex())

Output:

0100000002030000003132333435
like image 159
Mark Tolonen Avatar answered Oct 16 '25 21:10

Mark Tolonen



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!