Skip to content

Commit 18c1a8d

Browse files
matthiasgoergensgpsheadencukou
authored
gh-97588: Align ctypes struct layout to GCC/MSVC (GH-97702)
Structure layout, and especially bitfields, sometimes resulted in clearly wrong behaviour like overlapping fields. This fixes Co-authored-by: Gregory P. Smith <[email protected]> Co-authored-by: Petr Viktorin <[email protected]>
1 parent c1e9647 commit 18c1a8d

17 files changed

+3286
-188
lines changed

Doc/library/ctypes.rst

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -661,14 +661,18 @@ for debugging because they can provide useful information::
661661
guaranteed by the library to work in the general case. Unions and
662662
structures with bit-fields should always be passed to functions by pointer.
663663

664-
Structure/union alignment and byte order
665-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
666-
667-
By default, Structure and Union fields are aligned in the same way the C
668-
compiler does it. It is possible to override this behavior by specifying a
669-
:attr:`~Structure._pack_` class attribute in the subclass definition.
670-
This must be set to a positive integer and specifies the maximum alignment for the fields.
671-
This is what ``#pragma pack(n)`` also does in MSVC.
664+
Structure/union layout, alignment and byte order
665+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
666+
667+
By default, Structure and Union fields are laid out in the same way the C
668+
compiler does it. It is possible to override this behavior entirely by specifying a
669+
:attr:`~Structure._layout_` class attribute in the subclass definition; see
670+
the attribute documentation for details.
671+
672+
It is possible to specify the maximum alignment for the fields by setting
673+
the :attr:`~Structure._pack_` class attribute to a positive integer.
674+
This matches what ``#pragma pack(n)`` does in MSVC.
675+
672676
It is also possible to set a minimum alignment for how the subclass itself is packed in the
673677
same way ``#pragma align(n)`` works in MSVC.
674678
This can be achieved by specifying a ::attr:`~Structure._align_` class attribute
@@ -2540,6 +2544,31 @@ fields, or any other data types containing pointer type fields.
25402544
the structure when being packed or unpacked to/from memory.
25412545
Setting this attribute to 0 is the same as not setting it at all.
25422546

2547+
.. attribute:: _layout_
2548+
2549+
An optional string naming the struct/union layout. It can currently
2550+
be set to:
2551+
2552+
- ``"ms"``: the layout used by the Microsoft compiler (MSVC).
2553+
On GCC and Clang, this layout can be selected with
2554+
``__attribute__((ms_struct))``.
2555+
- ``"gcc-sysv"``: the layout used by GCC with the System V or “SysV-like”
2556+
data model, as used on Linux and macOS.
2557+
With this layout, :attr:`~Structure._pack_` must be unset or zero.
2558+
2559+
If not set explicitly, ``ctypes`` will use a default that
2560+
matches the platform conventions. This default may change in future
2561+
Python releases (for example, when a new platform gains official support,
2562+
or when a difference between similar platforms is found).
2563+
Currently the default will be:
2564+
2565+
- On Windows: ``"ms"``
2566+
- When :attr:`~Structure._pack_` is specified: ``"ms"``
2567+
- Otherwise: ``"gcc-sysv"``
2568+
2569+
:attr:`!_layout_` must already be defined when
2570+
:attr:`~Structure._fields_` is assigned, otherwise it will have no effect.
2571+
25432572
.. attribute:: _anonymous_
25442573

25452574
An optional sequence that lists the names of unnamed (anonymous) fields.

Doc/whatsnew/3.13.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,18 @@ copy
656656
any user classes which define the :meth:`!__replace__` method.
657657
(Contributed by Serhiy Storchaka in :gh:`108751`.)
658658

659+
ctypes
660+
------
661+
662+
* The layout of :ref:`bit fields <ctypes-bit-fields-in-structures-unions>` in
663+
:class:`~ctypes.Structure` and :class:`~ctypes.Union` was improved to better
664+
match platform defaults (GCC/Clang or MSC). In particular, fields no longer
665+
overlap.
666+
(Contributed by Matthias Görgens in :gh:`97702`.)
667+
* A :attr:`ctypes.Structure._layout_` class attribute can be set
668+
to help match a non-default ABI.
669+
(Contributed by Petr Viktorin in :gh:`97702`.)
670+
659671
dbm
660672
---
661673

Include/internal/pycore_global_objects_fini_generated.h

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_global_strings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ struct _Py_global_strings {
256256
STRUCT_FOR_ID(_initializing)
257257
STRUCT_FOR_ID(_io)
258258
STRUCT_FOR_ID(_is_text_encoding)
259+
STRUCT_FOR_ID(_layout_)
259260
STRUCT_FOR_ID(_length_)
260261
STRUCT_FOR_ID(_limbo)
261262
STRUCT_FOR_ID(_lock_unlock_module)

Include/internal/pycore_runtime_init_generated.h

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_unicodeobject_generated.h

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)