moog
moog

Reputation: 463

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?

Upvotes: 4

Views: 3265

Answers (1)

Mark Tolonen
Mark Tolonen

Reputation: 177891

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

Upvotes: 5

Related Questions