-
Notifications
You must be signed in to change notification settings - Fork 303
Description
IronPytthon always uses msvc bitfield alignment rules for bitfields in structures in ctypes
. According to these rules, a different type of a bitfield from the preceding one forces the compiler to align the new bitfield at its type's alignment boundary. On Windows, these are also the rules used by CPython.
On Unix platforms, however, CPython uses gcc alignment rules, which say that bitfields may be absorbed in the subsequent or preceding wider type, if they fit.
Example:
from ctypes import *
class X(Structure):
_fields_ = [
("a", c_byte, 4),
("b", c_byte, 6),
("c", c_short, 2),
]
print(sizeof(X))
IronPython (and CPython on Windows):
The structure size is 4. Although a
and b
have the same type, both do not fit in a single byte so b
is aligned with the next byte. Hence both fields take 2 bytes. c
has a different type than the preceding bitfield so it is also aligned at the next byte boundary so it adds 2 bytes to the overall size.
CPython (on Linux/macOS)
The structure size is 3. b
cannot be placed in the same bye as a
because their joint width (4+6) is more than 8 bits for a byte. So a
is the sole bitfield in the first byte of the structure. But b
can be (and is) merged with c
because their joint width (6 + 2) fits within 16 bits of a short int. This adds 2 bytes for the short int hosting both b
and c
. Note that this merging also happens if the order of b
and c
is reversed or if other integer types are used.
As a workaround, ctypes
structures depending on this type of compiler behaviour should be declared with all absorbed narrower fields to be of the type of the absorbing field. In the example above, declare b
as c_short
.