1 #ifndef Py_BUILD_CORE_BUILTIN
2 # define Py_BUILD_CORE_MODULE 1
3 #endif
4 #define NEEDS_PY_IDENTIFIER
5
6 #include "Python.h"
7 // windows.h must be included before pycore internal headers
8 #ifdef MS_WIN32
9 # include <windows.h>
10 #endif
11
12 #include "pycore_call.h" // _PyObject_CallNoArgs()
13 #include <ffi.h>
14 #ifdef MS_WIN32
15 # include <malloc.h>
16 #endif
17 #include "ctypes.h"
18
19 /******************************************************************/
20 /*
21 StdDict - a dictionary subclass, containing additional C accessible fields
22
23 XXX blabla more
24 */
25
26 /* Seems we need this, otherwise we get problems when calling
27 * PyDict_SetItem() (ma_lookup is NULL)
28 */
29 static int
30 PyCStgDict_init(StgDictObject *self, PyObject *args, PyObject *kwds)
31 {
32 if (PyDict_Type.tp_init((PyObject *)self, args, kwds) < 0)
33 return -1;
34 self->format = NULL;
35 self->ndim = 0;
36 self->shape = NULL;
37 return 0;
38 }
39
40 static int
41 PyCStgDict_clear(StgDictObject *self)
42 {
43 Py_CLEAR(self->proto);
44 Py_CLEAR(self->argtypes);
45 Py_CLEAR(self->converters);
46 Py_CLEAR(self->restype);
47 Py_CLEAR(self->checker);
48 return 0;
49 }
50
51 static void
52 PyCStgDict_dealloc(StgDictObject *self)
53 {
54 PyCStgDict_clear(self);
55 PyMem_Free(self->format);
56 PyMem_Free(self->shape);
57 PyMem_Free(self->ffi_type_pointer.elements);
58 PyDict_Type.tp_dealloc((PyObject *)self);
59 }
60
61 static PyObject *
62 PyCStgDict_sizeof(StgDictObject *self, void *unused)
63 {
64 Py_ssize_t res;
65
66 res = _PyDict_SizeOf((PyDictObject *)self);
67 res += sizeof(StgDictObject) - sizeof(PyDictObject);
68 if (self->format)
69 res += strlen(self->format) + 1;
70 res += self->ndim * sizeof(Py_ssize_t);
71 if (self->ffi_type_pointer.elements)
72 res += (self->length + 1) * sizeof(ffi_type *);
73 return PyLong_FromSsize_t(res);
74 }
75
76 int
77 PyCStgDict_clone(StgDictObject *dst, StgDictObject *src)
78 {
79 char *d, *s;
80 Py_ssize_t size;
81
82 PyCStgDict_clear(dst);
83 PyMem_Free(dst->ffi_type_pointer.elements);
84 PyMem_Free(dst->format);
85 dst->format = NULL;
86 PyMem_Free(dst->shape);
87 dst->shape = NULL;
88 dst->ffi_type_pointer.elements = NULL;
89
90 d = (char *)dst;
91 s = (char *)src;
92 memcpy(d + sizeof(PyDictObject),
93 s + sizeof(PyDictObject),
94 sizeof(StgDictObject) - sizeof(PyDictObject));
95
96 Py_XINCREF(dst->proto);
97 Py_XINCREF(dst->argtypes);
98 Py_XINCREF(dst->converters);
99 Py_XINCREF(dst->restype);
100 Py_XINCREF(dst->checker);
101
102 if (src->format) {
103 dst->format = PyMem_Malloc(strlen(src->format) + 1);
104 if (dst->format == NULL) {
105 PyErr_NoMemory();
106 return -1;
107 }
108 strcpy(dst->format, src->format);
109 }
110 if (src->shape) {
111 dst->shape = PyMem_Malloc(sizeof(Py_ssize_t) * src->ndim);
112 if (dst->shape == NULL) {
113 PyErr_NoMemory();
114 return -1;
115 }
116 memcpy(dst->shape, src->shape,
117 sizeof(Py_ssize_t) * src->ndim);
118 }
119
120 if (src->ffi_type_pointer.elements == NULL)
121 return 0;
122 size = sizeof(ffi_type *) * (src->length + 1);
123 dst->ffi_type_pointer.elements = PyMem_Malloc(size);
124 if (dst->ffi_type_pointer.elements == NULL) {
125 PyErr_NoMemory();
126 return -1;
127 }
128 memcpy(dst->ffi_type_pointer.elements,
129 src->ffi_type_pointer.elements,
130 size);
131 return 0;
132 }
133
134 static struct PyMethodDef PyCStgDict_methods[] = {
135 {"__sizeof__", (PyCFunction)PyCStgDict_sizeof, METH_NOARGS},
136 {NULL, NULL} /* sentinel */
137 };
138
139 PyTypeObject PyCStgDict_Type = {
140 PyVarObject_HEAD_INIT(NULL, 0)
141 "StgDict",
142 sizeof(StgDictObject),
143 0,
144 (destructor)PyCStgDict_dealloc, /* tp_dealloc */
145 0, /* tp_vectorcall_offset */
146 0, /* tp_getattr */
147 0, /* tp_setattr */
148 0, /* tp_as_async */
149 0, /* tp_repr */
150 0, /* tp_as_number */
151 0, /* tp_as_sequence */
152 0, /* tp_as_mapping */
153 0, /* tp_hash */
154 0, /* tp_call */
155 0, /* tp_str */
156 0, /* tp_getattro */
157 0, /* tp_setattro */
158 0, /* tp_as_buffer */
159 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
160 0, /* tp_doc */
161 0, /* tp_traverse */
162 0, /* tp_clear */
163 0, /* tp_richcompare */
164 0, /* tp_weaklistoffset */
165 0, /* tp_iter */
166 0, /* tp_iternext */
167 PyCStgDict_methods, /* tp_methods */
168 0, /* tp_members */
169 0, /* tp_getset */
170 0, /* tp_base */
171 0, /* tp_dict */
172 0, /* tp_descr_get */
173 0, /* tp_descr_set */
174 0, /* tp_dictoffset */
175 (initproc)PyCStgDict_init, /* tp_init */
176 0, /* tp_alloc */
177 0, /* tp_new */
178 0, /* tp_free */
179 };
180
181 /* May return NULL, but does not set an exception! */
182 StgDictObject *
183 PyType_stgdict(PyObject *obj)
184 {
185 PyTypeObject *type;
186
187 if (!PyType_Check(obj))
188 return NULL;
189 type = (PyTypeObject *)obj;
190 if (!type->tp_dict || !PyCStgDict_CheckExact(type->tp_dict))
191 return NULL;
192 return (StgDictObject *)type->tp_dict;
193 }
194
195 /* May return NULL, but does not set an exception! */
196 /*
197 This function should be as fast as possible, so we don't call PyType_stgdict
198 above but inline the code, and avoid the PyType_Check().
199 */
200 StgDictObject *
201 PyObject_stgdict(PyObject *self)
202 {
203 PyTypeObject *type = Py_TYPE(self);
204 if (!type->tp_dict || !PyCStgDict_CheckExact(type->tp_dict))
205 return NULL;
206 return (StgDictObject *)type->tp_dict;
207 }
208
209 /* descr is the descriptor for a field marked as anonymous. Get all the
210 _fields_ descriptors from descr->proto, create new descriptors with offset
211 and index adjusted, and stuff them into type.
212 */
213 static int
214 MakeFields(PyObject *type, CFieldObject *descr,
215 Py_ssize_t index, Py_ssize_t offset)
216 {
217 Py_ssize_t i;
218 PyObject *fields;
219 PyObject *fieldlist;
220
221 fields = PyObject_GetAttrString(descr->proto, "_fields_");
222 if (fields == NULL)
223 return -1;
224 fieldlist = PySequence_Fast(fields, "_fields_ must be a sequence");
225 Py_DECREF(fields);
226 if (fieldlist == NULL)
227 return -1;
228
229 for (i = 0; i < PySequence_Fast_GET_SIZE(fieldlist); ++i) {
230 PyObject *pair = PySequence_Fast_GET_ITEM(fieldlist, i); /* borrowed */
231 PyObject *fname, *ftype, *bits;
232 CFieldObject *fdescr;
233 CFieldObject *new_descr;
234 /* Convert to PyArg_UnpackTuple... */
235 if (!PyArg_ParseTuple(pair, "OO|O", &fname, &ftype, &bits)) {
236 Py_DECREF(fieldlist);
237 return -1;
238 }
239 fdescr = (CFieldObject *)PyObject_GetAttr(descr->proto, fname);
240 if (fdescr == NULL) {
241 Py_DECREF(fieldlist);
242 return -1;
243 }
244 if (!Py_IS_TYPE(fdescr, &PyCField_Type)) {
245 PyErr_SetString(PyExc_TypeError, "unexpected type");
246 Py_DECREF(fdescr);
247 Py_DECREF(fieldlist);
248 return -1;
249 }
250 if (fdescr->anonymous) {
251 int rc = MakeFields(type, fdescr,
252 index + fdescr->index,
253 offset + fdescr->offset);
254 Py_DECREF(fdescr);
255 if (rc == -1) {
256 Py_DECREF(fieldlist);
257 return -1;
258 }
259 continue;
260 }
261 new_descr = (CFieldObject *)PyCField_Type.tp_alloc((PyTypeObject *)&PyCField_Type, 0);
262 if (new_descr == NULL) {
263 Py_DECREF(fdescr);
264 Py_DECREF(fieldlist);
265 return -1;
266 }
267 assert(Py_IS_TYPE(new_descr, &PyCField_Type));
268 new_descr->size = fdescr->size;
269 new_descr->offset = fdescr->offset + offset;
270 new_descr->index = fdescr->index + index;
271 new_descr->proto = fdescr->proto;
272 Py_XINCREF(new_descr->proto);
273 new_descr->getfunc = fdescr->getfunc;
274 new_descr->setfunc = fdescr->setfunc;
275
276 Py_DECREF(fdescr);
277
278 if (-1 == PyObject_SetAttr(type, fname, (PyObject *)new_descr)) {
279 Py_DECREF(fieldlist);
280 Py_DECREF(new_descr);
281 return -1;
282 }
283 Py_DECREF(new_descr);
284 }
285 Py_DECREF(fieldlist);
286 return 0;
287 }
288
289 /* Iterate over the names in the type's _anonymous_ attribute, if present,
290 */
291 static int
292 MakeAnonFields(PyObject *type)
293 {
294 _Py_IDENTIFIER(_anonymous_);
295 PyObject *anon;
296 PyObject *anon_names;
297 Py_ssize_t i;
298
299 if (_PyObject_LookupAttrId(type, &PyId__anonymous_, &anon) < 0) {
300 return -1;
301 }
302 if (anon == NULL) {
303 return 0;
304 }
305 anon_names = PySequence_Fast(anon, "_anonymous_ must be a sequence");
306 Py_DECREF(anon);
307 if (anon_names == NULL)
308 return -1;
309
310 for (i = 0; i < PySequence_Fast_GET_SIZE(anon_names); ++i) {
311 PyObject *fname = PySequence_Fast_GET_ITEM(anon_names, i); /* borrowed */
312 CFieldObject *descr = (CFieldObject *)PyObject_GetAttr(type, fname);
313 if (descr == NULL) {
314 Py_DECREF(anon_names);
315 return -1;
316 }
317 if (!Py_IS_TYPE(descr, &PyCField_Type)) {
318 PyErr_Format(PyExc_AttributeError,
319 "'%U' is specified in _anonymous_ but not in "
320 "_fields_",
321 fname);
322 Py_DECREF(anon_names);
323 Py_DECREF(descr);
324 return -1;
325 }
326 descr->anonymous = 1;
327
328 /* descr is in the field descriptor. */
329 if (-1 == MakeFields(type, (CFieldObject *)descr,
330 ((CFieldObject *)descr)->index,
331 ((CFieldObject *)descr)->offset)) {
332 Py_DECREF(descr);
333 Py_DECREF(anon_names);
334 return -1;
335 }
336 Py_DECREF(descr);
337 }
338
339 Py_DECREF(anon_names);
340 return 0;
341 }
342
343 /*
344 Retrieve the (optional) _pack_ attribute from a type, the _fields_ attribute,
345 and create an StgDictObject. Used for Structure and Union subclasses.
346 */
347 int
348 PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct)
349 {
350 _Py_IDENTIFIER(_swappedbytes_);
351 _Py_IDENTIFIER(_use_broken_old_ctypes_structure_semantics_);
352 _Py_IDENTIFIER(_pack_);
353 StgDictObject *stgdict, *basedict;
354 Py_ssize_t len, offset, size, align, i;
355 Py_ssize_t union_size, total_align;
356 Py_ssize_t field_size = 0;
357 int bitofs;
358 PyObject *tmp;
359 int isPacked;
360 int pack;
361 Py_ssize_t ffi_ofs;
362 int big_endian;
363 int arrays_seen = 0;
364
365 /* HACK Alert: I cannot be bothered to fix ctypes.com, so there has to
366 be a way to use the old, broken semantics: _fields_ are not extended
367 but replaced in subclasses.
368
369 XXX Remove this in ctypes 1.0!
370 */
371 int use_broken_old_ctypes_semantics;
372
373 if (fields == NULL)
374 return 0;
375
376 if (_PyObject_LookupAttrId(type, &PyId__swappedbytes_, &tmp) < 0) {
377 return -1;
378 }
379 if (tmp) {
380 Py_DECREF(tmp);
381 big_endian = !PY_BIG_ENDIAN;
382 }
383 else {
384 big_endian = PY_BIG_ENDIAN;
385 }
386
387 if (_PyObject_LookupAttrId(type,
388 &PyId__use_broken_old_ctypes_structure_semantics_, &tmp) < 0)
389 {
390 return -1;
391 }
392 if (tmp) {
393 Py_DECREF(tmp);
394 use_broken_old_ctypes_semantics = 1;
395 }
396 else {
397 use_broken_old_ctypes_semantics = 0;
398 }
399
400 if (_PyObject_LookupAttrId(type, &PyId__pack_, &tmp) < 0) {
401 return -1;
402 }
403 if (tmp) {
404 isPacked = 1;
405 pack = _PyLong_AsInt(tmp);
406 Py_DECREF(tmp);
407 if (pack < 0) {
408 if (!PyErr_Occurred() ||
409 PyErr_ExceptionMatches(PyExc_TypeError) ||
410 PyErr_ExceptionMatches(PyExc_OverflowError))
411 {
412 PyErr_SetString(PyExc_ValueError,
413 "_pack_ must be a non-negative integer");
414 }
415 return -1;
416 }
417 }
418 else {
419 isPacked = 0;
420 pack = 0;
421 }
422
423 len = PySequence_Size(fields);
424 if (len == -1) {
425 if (PyErr_ExceptionMatches(PyExc_TypeError)) {
426 PyErr_SetString(PyExc_TypeError,
427 "'_fields_' must be a sequence of pairs");
428 }
429 return -1;
430 }
431
432 stgdict = PyType_stgdict(type);
433 if (!stgdict) {
434 PyErr_SetString(PyExc_TypeError,
435 "ctypes state is not initialized");
436 return -1;
437 }
438 /* If this structure/union is already marked final we cannot assign
439 _fields_ anymore. */
440
441 if (stgdict->flags & DICTFLAG_FINAL) {/* is final ? */
442 PyErr_SetString(PyExc_AttributeError,
443 "_fields_ is final");
444 return -1;
445 }
446
447 if (stgdict->format) {
448 PyMem_Free(stgdict->format);
449 stgdict->format = NULL;
450 }
451
452 if (stgdict->ffi_type_pointer.elements)
453 PyMem_Free(stgdict->ffi_type_pointer.elements);
454
455 basedict = PyType_stgdict((PyObject *)((PyTypeObject *)type)->tp_base);
456 if (basedict) {
457 stgdict->flags |= (basedict->flags &
458 (TYPEFLAG_HASUNION | TYPEFLAG_HASBITFIELD));
459 }
460 if (!isStruct) {
461 stgdict->flags |= TYPEFLAG_HASUNION;
462 }
463 if (basedict && !use_broken_old_ctypes_semantics) {
464 size = offset = basedict->size;
465 align = basedict->align;
466 union_size = 0;
467 total_align = align ? align : 1;
468 stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT;
469 stgdict->ffi_type_pointer.elements = PyMem_New(ffi_type *, basedict->length + len + 1);
470 if (stgdict->ffi_type_pointer.elements == NULL) {
471 PyErr_NoMemory();
472 return -1;
473 }
474 memset(stgdict->ffi_type_pointer.elements, 0,
475 sizeof(ffi_type *) * (basedict->length + len + 1));
476 if (basedict->length > 0) {
477 memcpy(stgdict->ffi_type_pointer.elements,
478 basedict->ffi_type_pointer.elements,
479 sizeof(ffi_type *) * (basedict->length));
480 }
481 ffi_ofs = basedict->length;
482 } else {
483 offset = 0;
484 size = 0;
485 align = 0;
486 union_size = 0;
487 total_align = 1;
488 stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT;
489 stgdict->ffi_type_pointer.elements = PyMem_New(ffi_type *, len + 1);
490 if (stgdict->ffi_type_pointer.elements == NULL) {
491 PyErr_NoMemory();
492 return -1;
493 }
494 memset(stgdict->ffi_type_pointer.elements, 0,
495 sizeof(ffi_type *) * (len + 1));
496 ffi_ofs = 0;
497 }
498
499 assert(stgdict->format == NULL);
500 if (isStruct && !isPacked) {
501 stgdict->format = _ctypes_alloc_format_string(NULL, "T{");
502 } else {
503 /* PEP3118 doesn't support union, or packed structures (well,
504 only standard packing, but we don't support the pep for
505 that). Use 'B' for bytes. */
506 stgdict->format = _ctypes_alloc_format_string(NULL, "B");
507 }
508 if (stgdict->format == NULL)
509 return -1;
510
511 for (i = 0; i < len; ++i) {
512 PyObject *name = NULL, *desc = NULL;
513 PyObject *pair = PySequence_GetItem(fields, i);
514 PyObject *prop;
515 StgDictObject *dict;
516 int bitsize = 0;
517
518 if (!pair || !PyArg_ParseTuple(pair, "UO|i", &name, &desc, &bitsize)) {
519 PyErr_SetString(PyExc_TypeError,
520 "'_fields_' must be a sequence of (name, C type) pairs");
521 Py_XDECREF(pair);
522 return -1;
523 }
524 if (PyCArrayTypeObject_Check(desc))
525 arrays_seen = 1;
526 dict = PyType_stgdict(desc);
527 if (dict == NULL) {
528 Py_DECREF(pair);
529 PyErr_Format(PyExc_TypeError,
530 "second item in _fields_ tuple (index %zd) must be a C type",
531 i);
532 return -1;
533 }
534 stgdict->ffi_type_pointer.elements[ffi_ofs + i] = &dict->ffi_type_pointer;
535 if (dict->flags & (TYPEFLAG_ISPOINTER | TYPEFLAG_HASPOINTER))
536 stgdict->flags |= TYPEFLAG_HASPOINTER;
537 stgdict->flags |= dict->flags & (TYPEFLAG_HASUNION | TYPEFLAG_HASBITFIELD);
538 dict->flags |= DICTFLAG_FINAL; /* mark field type final */
539 if (PyTuple_Size(pair) == 3) { /* bits specified */
540 stgdict->flags |= TYPEFLAG_HASBITFIELD;
541 switch(dict->ffi_type_pointer.type) {
542 case FFI_TYPE_UINT8:
543 case FFI_TYPE_UINT16:
544 case FFI_TYPE_UINT32:
545 case FFI_TYPE_SINT64:
546 case FFI_TYPE_UINT64:
547 break;
548
549 case FFI_TYPE_SINT8:
550 case FFI_TYPE_SINT16:
551 case FFI_TYPE_SINT32:
552 if (dict->getfunc != _ctypes_get_fielddesc("c")->getfunc
553 && dict->getfunc != _ctypes_get_fielddesc("u")->getfunc
554 )
555 break;
556 /* else fall through */
557 default:
558 PyErr_Format(PyExc_TypeError,
559 "bit fields not allowed for type %s",
560 ((PyTypeObject *)desc)->tp_name);
561 Py_DECREF(pair);
562 return -1;
563 }
564 if (bitsize <= 0 || bitsize > dict->size * 8) {
565 PyErr_SetString(PyExc_ValueError,
566 "number of bits invalid for bit field");
567 Py_DECREF(pair);
568 return -1;
569 }
570 } else
571 bitsize = 0;
572
573 if (isStruct && !isPacked) {
574 const char *fieldfmt = dict->format ? dict->format : "B";
575 const char *fieldname = PyUnicode_AsUTF8(name);
576 char *ptr;
577 Py_ssize_t len;
578 char *buf;
579
580 if (fieldname == NULL)
581 {
582 Py_DECREF(pair);
583 return -1;
584 }
585
586 len = strlen(fieldname) + strlen(fieldfmt);
587
588 buf = PyMem_Malloc(len + 2 + 1);
589 if (buf == NULL) {
590 Py_DECREF(pair);
591 PyErr_NoMemory();
592 return -1;
593 }
594 sprintf(buf, "%s:%s:", fieldfmt, fieldname);
595
596 ptr = stgdict->format;
597 if (dict->shape != NULL) {
598 stgdict->format = _ctypes_alloc_format_string_with_shape(
599 dict->ndim, dict->shape, stgdict->format, buf);
600 } else {
601 stgdict->format = _ctypes_alloc_format_string(stgdict->format, buf);
602 }
603 PyMem_Free(ptr);
604 PyMem_Free(buf);
605
606 if (stgdict->format == NULL) {
607 Py_DECREF(pair);
608 return -1;
609 }
610 }
611
612 if (isStruct) {
613 prop = PyCField_FromDesc(desc, i,
614 &field_size, bitsize, &bitofs,
615 &size, &offset, &align,
616 pack, big_endian);
617 } else /* union */ {
618 size = 0;
619 offset = 0;
620 align = 0;
621 prop = PyCField_FromDesc(desc, i,
622 &field_size, bitsize, &bitofs,
623 &size, &offset, &align,
624 pack, big_endian);
625 union_size = max(size, union_size);
626 }
627 total_align = max(align, total_align);
628
629 if (!prop) {
630 Py_DECREF(pair);
631 return -1;
632 }
633 if (-1 == PyObject_SetAttr(type, name, prop)) {
634 Py_DECREF(prop);
635 Py_DECREF(pair);
636 return -1;
637 }
638 Py_DECREF(pair);
639 Py_DECREF(prop);
640 }
641
642 if (isStruct && !isPacked) {
643 char *ptr = stgdict->format;
644 stgdict->format = _ctypes_alloc_format_string(stgdict->format, "}");
645 PyMem_Free(ptr);
646 if (stgdict->format == NULL)
647 return -1;
648 }
649
650 if (!isStruct)
651 size = union_size;
652
653 /* Adjust the size according to the alignment requirements */
654 size = ((size + total_align - 1) / total_align) * total_align;
655
656 stgdict->ffi_type_pointer.alignment = Py_SAFE_DOWNCAST(total_align,
657 Py_ssize_t,
658 unsigned short);
659 stgdict->ffi_type_pointer.size = size;
660
661 stgdict->size = size;
662 stgdict->align = total_align;
663 stgdict->length = len; /* ADD ffi_ofs? */
664
665 #define MAX_STRUCT_SIZE 16
666
667 if (arrays_seen && (size <= MAX_STRUCT_SIZE)) {
668 /*
669 * See bpo-22273. Arrays are normally treated as pointers, which is
670 * fine when an array name is being passed as parameter, but not when
671 * passing structures by value that contain arrays. On 64-bit Linux,
672 * small structures passed by value are passed in registers, and in
673 * order to do this, libffi needs to know the true type of the array
674 * members of structs. Treating them as pointers breaks things.
675 *
676 * By small structures, we mean ones that are 16 bytes or less. In that
677 * case, there can't be more than 16 elements after unrolling arrays,
678 * as we (will) disallow bitfields. So we can collect the true ffi_type
679 * values in a fixed-size local array on the stack and, if any arrays
680 * were seen, replace the ffi_type_pointer.elements with a more
681 * accurate set, to allow libffi to marshal them into registers
682 * correctly. It means one more loop over the fields, but if we got
683 * here, the structure is small, so there aren't too many of those.
684 *
685 * Although the passing in registers is specific to 64-bit Linux, the
686 * array-in-struct vs. pointer problem is general. But we restrict the
687 * type transformation to small structs nonetheless.
688 *
689 * Note that although a union may be small in terms of memory usage, it
690 * could contain many overlapping declarations of arrays, e.g.
691 *
692 * union {
693 * unsigned int_8 foo [16];
694 * unsigned uint_8 bar [16];
695 * unsigned int_16 baz[8];
696 * unsigned uint_16 bozz[8];
697 * unsigned int_32 fizz[4];
698 * unsigned uint_32 buzz[4];
699 * }
700 *
701 * which is still only 16 bytes in size. We need to convert this into
702 * the following equivalent for libffi:
703 *
704 * union {
705 * struct { int_8 e1; int_8 e2; ... int_8 e_16; } f1;
706 * struct { uint_8 e1; uint_8 e2; ... uint_8 e_16; } f2;
707 * struct { int_16 e1; int_16 e2; ... int_16 e_8; } f3;
708 * struct { uint_16 e1; uint_16 e2; ... uint_16 e_8; } f4;
709 * struct { int_32 e1; int_32 e2; ... int_32 e_4; } f5;
710 * struct { uint_32 e1; uint_32 e2; ... uint_32 e_4; } f6;
711 * }
712 *
713 * So the struct/union needs setting up as follows: all non-array
714 * elements copied across as is, and all array elements replaced with
715 * an equivalent struct which has as many fields as the array has
716 * elements, plus one NULL pointer.
717 */
718
719 Py_ssize_t num_ffi_type_pointers = 0; /* for the dummy fields */
720 Py_ssize_t num_ffi_types = 0; /* for the dummy structures */
721 size_t alloc_size; /* total bytes to allocate */
722 void *type_block; /* to hold all the type information needed */
723 ffi_type **element_types; /* of this struct/union */
724 ffi_type **dummy_types; /* of the dummy struct elements */
725 ffi_type *structs; /* point to struct aliases of arrays */
726 Py_ssize_t element_index; /* index into element_types for this */
727 Py_ssize_t dummy_index = 0; /* index into dummy field pointers */
728 Py_ssize_t struct_index = 0; /* index into dummy structs */
729
730 /* first pass to see how much memory to allocate */
731 for (i = 0; i < len; ++i) {
732 PyObject *name, *desc;
733 PyObject *pair = PySequence_GetItem(fields, i);
734 StgDictObject *dict;
735 int bitsize = 0;
736
737 if (pair == NULL) {
738 return -1;
739 }
740 if (!PyArg_ParseTuple(pair, "UO|i", &name, &desc, &bitsize)) {
741 PyErr_SetString(PyExc_TypeError,
742 "'_fields_' must be a sequence of (name, C type) pairs");
743 Py_DECREF(pair);
744 return -1;
745 }
746 dict = PyType_stgdict(desc);
747 if (dict == NULL) {
748 Py_DECREF(pair);
749 PyErr_Format(PyExc_TypeError,
750 "second item in _fields_ tuple (index %zd) must be a C type",
751 i);
752 return -1;
753 }
754 if (!PyCArrayTypeObject_Check(desc)) {
755 /* Not an array. Just need an ffi_type pointer. */
756 num_ffi_type_pointers++;
757 }
758 else {
759 /* It's an array. */
760 Py_ssize_t length = dict->length;
761 StgDictObject *edict;
762
763 edict = PyType_stgdict(dict->proto);
764 if (edict == NULL) {
765 Py_DECREF(pair);
766 PyErr_Format(PyExc_TypeError,
767 "second item in _fields_ tuple (index %zd) must be a C type",
768 i);
769 return -1;
770 }
771 /*
772 * We need one extra ffi_type to hold the struct, and one
773 * ffi_type pointer per array element + one for a NULL to
774 * mark the end.
775 */
776 num_ffi_types++;
777 num_ffi_type_pointers += length + 1;
778 }
779 Py_DECREF(pair);
780 }
781
782 /*
783 * At this point, we know we need storage for some ffi_types and some
784 * ffi_type pointers. We'll allocate these in one block.
785 * There are three sub-blocks of information: the ffi_type pointers to
786 * this structure/union's elements, the ffi_type_pointers to the
787 * dummy fields standing in for array elements, and the
788 * ffi_types representing the dummy structures.
789 */
790 alloc_size = (ffi_ofs + 1 + len + num_ffi_type_pointers) * sizeof(ffi_type *) +
791 num_ffi_types * sizeof(ffi_type);
792 type_block = PyMem_Malloc(alloc_size);
793
794 if (type_block == NULL) {
795 PyErr_NoMemory();
796 return -1;
797 }
798 /*
799 * the first block takes up ffi_ofs + len + 1 which is the pointers *
800 * for this struct/union. The second block takes up
801 * num_ffi_type_pointers, so the sum of these is ffi_ofs + len + 1 +
802 * num_ffi_type_pointers as allocated above. The last bit is the
803 * num_ffi_types structs.
804 */
805 element_types = (ffi_type **) type_block;
806 dummy_types = &element_types[ffi_ofs + len + 1];
807 structs = (ffi_type *) &dummy_types[num_ffi_type_pointers];
808
809 if (num_ffi_types > 0) {
810 memset(structs, 0, num_ffi_types * sizeof(ffi_type));
811 }
812 if (ffi_ofs && (basedict != NULL)) {
813 memcpy(element_types,
814 basedict->ffi_type_pointer.elements,
815 ffi_ofs * sizeof(ffi_type *));
816 }
817 element_index = ffi_ofs;
818
819 /* second pass to actually set the type pointers */
820 for (i = 0; i < len; ++i) {
821 PyObject *name, *desc;
822 PyObject *pair = PySequence_GetItem(fields, i);
823 StgDictObject *dict;
824 int bitsize = 0;
825
826 if (pair == NULL) {
827 PyMem_Free(type_block);
828 return -1;
829 }
830 /* In theory, we made this call in the first pass, so it *shouldn't*
831 * fail. However, you never know, and the code above might change
832 * later - keeping the check in here is a tad defensive but it
833 * will affect program size only slightly and performance hardly at
834 * all.
835 */
836 if (!PyArg_ParseTuple(pair, "UO|i", &name, &desc, &bitsize)) {
837 PyErr_SetString(PyExc_TypeError,
838 "'_fields_' must be a sequence of (name, C type) pairs");
839 Py_DECREF(pair);
840 PyMem_Free(type_block);
841 return -1;
842 }
843 dict = PyType_stgdict(desc);
844 /* Possibly this check could be avoided, but see above comment. */
845 if (dict == NULL) {
846 Py_DECREF(pair);
847 PyMem_Free(type_block);
848 PyErr_Format(PyExc_TypeError,
849 "second item in _fields_ tuple (index %zd) must be a C type",
850 i);
851 return -1;
852 }
853 assert(element_index < (ffi_ofs + len)); /* will be used below */
854 if (!PyCArrayTypeObject_Check(desc)) {
855 /* Not an array. Just copy over the element ffi_type. */
856 element_types[element_index++] = &dict->ffi_type_pointer;
857 }
858 else {
859 Py_ssize_t length = dict->length;
860 StgDictObject *edict;
861
862 edict = PyType_stgdict(dict->proto);
863 if (edict == NULL) {
864 Py_DECREF(pair);
865 PyMem_Free(type_block);
866 PyErr_Format(PyExc_TypeError,
867 "second item in _fields_ tuple (index %zd) must be a C type",
868 i);
869 return -1;
870 }
871 element_types[element_index++] = &structs[struct_index];
872 structs[struct_index].size = length * edict->ffi_type_pointer.size;
873 structs[struct_index].alignment = edict->ffi_type_pointer.alignment;
874 structs[struct_index].type = FFI_TYPE_STRUCT;
875 structs[struct_index].elements = &dummy_types[dummy_index];
876 ++struct_index;
877 /* Copy over the element's type, length times. */
878 while (length > 0) {
879 assert(dummy_index < (num_ffi_type_pointers));
880 dummy_types[dummy_index++] = &edict->ffi_type_pointer;
881 length--;
882 }
883 assert(dummy_index < (num_ffi_type_pointers));
884 dummy_types[dummy_index++] = NULL;
885 }
886 Py_DECREF(pair);
887 }
888
889 element_types[element_index] = NULL;
890 /*
891 * Replace the old elements with the new, taking into account
892 * base class elements where necessary.
893 */
894 assert(stgdict->ffi_type_pointer.elements);
895 PyMem_Free(stgdict->ffi_type_pointer.elements);
896 stgdict->ffi_type_pointer.elements = element_types;
897 }
898
899 /* We did check that this flag was NOT set above, it must not
900 have been set until now. */
901 if (stgdict->flags & DICTFLAG_FINAL) {
902 PyErr_SetString(PyExc_AttributeError,
903 "Structure or union cannot contain itself");
904 return -1;
905 }
906 stgdict->flags |= DICTFLAG_FINAL;
907
908 return MakeAnonFields(type);
909 }