Skip to content

Commit e3ad227

Browse files
committed
Add optional _align_ attribute to ctypes.Structure
1 parent 0ee2d77 commit e3ad227

File tree

5 files changed

+31
-2
lines changed

5 files changed

+31
-2
lines changed

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
@@ -231,6 +231,7 @@ struct _Py_global_strings {
231231
STRUCT_FOR_ID(_abc_impl)
232232
STRUCT_FOR_ID(_abstract_)
233233
STRUCT_FOR_ID(_active)
234+
STRUCT_FOR_ID(_align_)
234235
STRUCT_FOR_ID(_annotation)
235236
STRUCT_FOR_ID(_anonymous_)
236237
STRUCT_FOR_ID(_argtypes_)

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.

Modules/_ctypes/stgdict.c

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct
379379
int bitofs;
380380
PyObject *tmp;
381381
int pack;
382+
int forced_alignment = 1;
382383
Py_ssize_t ffi_ofs;
383384
int big_endian;
384385
int arrays_seen = 0;
@@ -419,6 +420,28 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct
419420
pack = 0;
420421
}
421422

423+
if (PyObject_GetOptionalAttr(type, &_Py_ID(_align_), &tmp) < 0) {
424+
return -1;
425+
}
426+
if (tmp) {
427+
forced_alignment = PyLong_AsInt(tmp);
428+
Py_DECREF(tmp);
429+
if (forced_alignment < 0) {
430+
if (!PyErr_Occurred() ||
431+
PyErr_ExceptionMatches(PyExc_TypeError) ||
432+
PyErr_ExceptionMatches(PyExc_OverflowError))
433+
{
434+
PyErr_SetString(PyExc_ValueError,
435+
"_align_ must be a non-negative integer");
436+
}
437+
return -1;
438+
}
439+
}
440+
else {
441+
/* Setting `_align_ = 0` amounts to using the default alignment */
442+
forced_alignment = 1;
443+
}
444+
422445
len = PySequence_Size(fields);
423446
if (len == -1) {
424447
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
@@ -463,7 +486,7 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct
463486
size = offset = basedict->size;
464487
align = basedict->align;
465488
union_size = 0;
466-
total_align = align ? align : 1;
489+
total_align = align ? align : forced_alignment;
467490
stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT;
468491
stgdict->ffi_type_pointer.elements = PyMem_New(ffi_type *, basedict->length + len + 1);
469492
if (stgdict->ffi_type_pointer.elements == NULL) {
@@ -483,7 +506,7 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct
483506
size = 0;
484507
align = 0;
485508
union_size = 0;
486-
total_align = 1;
509+
total_align = forced_alignment;
487510
stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT;
488511
stgdict->ffi_type_pointer.elements = PyMem_New(ffi_type *, len + 1);
489512
if (stgdict->ffi_type_pointer.elements == NULL) {

0 commit comments

Comments
 (0)