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