Currently, there is no real way to create a ctypes.Structure
which has some fixed minimum alignment.
It is easy to go the other way and set the maximum alignment by using the _pack_
attribute on the class, however for classes which you’d like to set a minimum alignment this is not possible at all it seems.
Consider the following example where we are trying to map some binary data to a structure, but one of the types comes from c++ where there struct is aligned to 16 bytes (IDString
in this example).
class IDString(ctypes.Structure):
_fields_ = [
("string", ctypes.c_char * 0x10),
]
class main(ctypes.Structure):
_fields_ = [
("first", ctypes.c_uint32),
("second", ctypes.c_ubyte),
("string", IDString),
]
data = bytearray(
b"\x07\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
b"\x68\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64\x21\x00\x00\x00\x00"
)
m = main.from_buffer(data)
print(f"first: {m.first}") # first: 7
print(f"second: {m.second}") # second: 1
print(f"string: {m.string.string}") # string: b''
However, if we have a way to indicate how the ctypes.Structure
should be aligned, such as:
class IDString(ctypes.Structure):
_align_ = 0x10
_fields_ = [
("string", ctypes.c_char * 0x10),
]
...
print(f"string: {m.string.string}") # string: b'hello world!'
Then we would be able to easily map this data without needing to add any annoying padding bytes which may all have to manually calculated if the structs have many fields which have alignment like this.
I have already made a sample implementation to make sure it works as intended and so would love some community feedback on this new feature I am proposing.
I think it is reasonable since we support #pragma pack
with the _pack_
attribute, so to support #pragma align
with an _align_
attribute seems sensible. It is also backward compatible since not having the attribute will just work how it did before.