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 = Py_TYPE(self);
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_IS_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_IS_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_IS_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 && dict->getfunc != _ctypes_get_fielddesc("u")->getfunc
542 )
543 break;
544 /* else fall through */
545 default:
546 PyErr_Format(PyExc_TypeError,
547 "bit fields not allowed for type %s",
548 ((PyTypeObject *)desc)->tp_name);
549 Py_DECREF(pair);
550 return -1;
551 }
552 if (bitsize <= 0 || bitsize > dict->size * 8) {
553 PyErr_SetString(PyExc_ValueError,
554 "number of bits invalid for bit field");
555 Py_DECREF(pair);
556 return -1;
557 }
558 } else
559 bitsize = 0;
560
561 if (isStruct && !isPacked) {
562 const char *fieldfmt = dict->format ? dict->format : "B";
563 const char *fieldname = PyUnicode_AsUTF8(name);
564 char *ptr;
565 Py_ssize_t len;
566 char *buf;
567
568 if (fieldname == NULL)
569 {
570 Py_DECREF(pair);
571 return -1;
572 }
573
574 len = strlen(fieldname) + strlen(fieldfmt);
575
576 buf = PyMem_Malloc(len + 2 + 1);
577 if (buf == NULL) {
578 Py_DECREF(pair);
579 PyErr_NoMemory();
580 return -1;
581 }
582 sprintf(buf, "%s:%s:", fieldfmt, fieldname);
583
584 ptr = stgdict->format;
585 if (dict->shape != NULL) {
586 stgdict->format = _ctypes_alloc_format_string_with_shape(
587 dict->ndim, dict->shape, stgdict->format, buf);
588 } else {
589 stgdict->format = _ctypes_alloc_format_string(stgdict->format, buf);
590 }
591 PyMem_Free(ptr);
592 PyMem_Free(buf);
593
594 if (stgdict->format == NULL) {
595 Py_DECREF(pair);
596 return -1;
597 }
598 }
599
600 if (isStruct) {
601 prop = PyCField_FromDesc(desc, i,
602 &field_size, bitsize, &bitofs,
603 &size, &offset, &align,
604 pack, big_endian);
605 } else /* union */ {
606 size = 0;
607 offset = 0;
608 align = 0;
609 prop = PyCField_FromDesc(desc, i,
610 &field_size, bitsize, &bitofs,
611 &size, &offset, &align,
612 pack, big_endian);
613 union_size = max(size, union_size);
614 }
615 total_align = max(align, total_align);
616
617 if (!prop) {
618 Py_DECREF(pair);
619 return -1;
620 }
621 if (-1 == PyObject_SetAttr(type, name, prop)) {
622 Py_DECREF(prop);
623 Py_DECREF(pair);
624 return -1;
625 }
626 Py_DECREF(pair);
627 Py_DECREF(prop);
628 }
629 #undef realdict
630
631 if (isStruct && !isPacked) {
632 char *ptr = stgdict->format;
633 stgdict->format = _ctypes_alloc_format_string(stgdict->format, "}");
634 PyMem_Free(ptr);
635 if (stgdict->format == NULL)
636 return -1;
637 }
638
639 if (!isStruct)
640 size = union_size;
641
642 /* Adjust the size according to the alignment requirements */
643 size = ((size + total_align - 1) / total_align) * total_align;
644
645 stgdict->ffi_type_pointer.alignment = Py_SAFE_DOWNCAST(total_align,
646 Py_ssize_t,
647 unsigned short);
648 stgdict->ffi_type_pointer.size = size;
649
650 stgdict->size = size;
651 stgdict->align = total_align;
652 stgdict->length = len; /* ADD ffi_ofs? */
653
654 #define MAX_STRUCT_SIZE 16
655
656 if (arrays_seen && (size <= MAX_STRUCT_SIZE)) {
657 /*
658 * See bpo-22273. Arrays are normally treated as pointers, which is
659 * fine when an array name is being passed as parameter, but not when
660 * passing structures by value that contain arrays. On 64-bit Linux,
661 * small structures passed by value are passed in registers, and in
662 * order to do this, libffi needs to know the true type of the array
663 * members of structs. Treating them as pointers breaks things.
664 *
665 * By small structures, we mean ones that are 16 bytes or less. In that
666 * case, there can't be more than 16 elements after unrolling arrays,
667 * as we (will) disallow bitfields. So we can collect the true ffi_type
668 * values in a fixed-size local array on the stack and, if any arrays
669 * were seen, replace the ffi_type_pointer.elements with a more
670 * accurate set, to allow libffi to marshal them into registers
671 * correctly. It means one more loop over the fields, but if we got
672 * here, the structure is small, so there aren't too many of those.
673 *
674 * Although the passing in registers is specific to 64-bit Linux, the
675 * array-in-struct vs. pointer problem is general. But we restrict the
676 * type transformation to small structs nonetheless.
677 *
678 * Note that although a union may be small in terms of memory usage, it
679 * could contain many overlapping declarations of arrays, e.g.
680 *
681 * union {
682 * unsigned int_8 foo [16];
683 * unsigned uint_8 bar [16];
684 * unsigned int_16 baz[8];
685 * unsigned uint_16 bozz[8];
686 * unsigned int_32 fizz[4];
687 * unsigned uint_32 buzz[4];
688 * }
689 *
690 * which is still only 16 bytes in size. We need to convert this into
691 * the following equivalent for libffi:
692 *
693 * union {
694 * struct { int_8 e1; int_8 e2; ... int_8 e_16; } f1;
695 * struct { uint_8 e1; uint_8 e2; ... uint_8 e_16; } f2;
696 * struct { int_16 e1; int_16 e2; ... int_16 e_8; } f3;
697 * struct { uint_16 e1; uint_16 e2; ... uint_16 e_8; } f4;
698 * struct { int_32 e1; int_32 e2; ... int_32 e_4; } f5;
699 * struct { uint_32 e1; uint_32 e2; ... uint_32 e_4; } f6;
700 * }
701 *
702 * So the struct/union needs setting up as follows: all non-array
703 * elements copied across as is, and all array elements replaced with
704 * an equivalent struct which has as many fields as the array has
705 * elements, plus one NULL pointer.
706 */
707
708 Py_ssize_t num_ffi_type_pointers = 0; /* for the dummy fields */
709 Py_ssize_t num_ffi_types = 0; /* for the dummy structures */
710 size_t alloc_size; /* total bytes to allocate */
711 void *type_block; /* to hold all the type information needed */
712 ffi_type **element_types; /* of this struct/union */
713 ffi_type **dummy_types; /* of the dummy struct elements */
714 ffi_type *structs; /* point to struct aliases of arrays */
715 Py_ssize_t element_index; /* index into element_types for this */
716 Py_ssize_t dummy_index = 0; /* index into dummy field pointers */
717 Py_ssize_t struct_index = 0; /* index into dummy structs */
718
719 /* first pass to see how much memory to allocate */
720 for (i = 0; i < len; ++i) {
721 PyObject *name, *desc;
722 PyObject *pair = PySequence_GetItem(fields, i);
723 StgDictObject *dict;
724 int bitsize = 0;
725
726 if (pair == NULL) {
727 return -1;
728 }
729 if (!PyArg_ParseTuple(pair, "UO|i", &name, &desc, &bitsize)) {
730 PyErr_SetString(PyExc_TypeError,
731 "'_fields_' must be a sequence of (name, C type) pairs");
732 Py_DECREF(pair);
733 return -1;
734 }
735 dict = PyType_stgdict(desc);
736 if (dict == NULL) {
737 Py_DECREF(pair);
738 PyErr_Format(PyExc_TypeError,
739 "second item in _fields_ tuple (index %zd) must be a C type",
740 i);
741 return -1;
742 }
743 if (!PyCArrayTypeObject_Check(desc)) {
744 /* Not an array. Just need an ffi_type pointer. */
745 num_ffi_type_pointers++;
746 }
747 else {
748 /* It's an array. */
749 Py_ssize_t length = dict->length;
750 StgDictObject *edict;
751
752 edict = PyType_stgdict(dict->proto);
753 if (edict == NULL) {
754 Py_DECREF(pair);
755 PyErr_Format(PyExc_TypeError,
756 "second item in _fields_ tuple (index %zd) must be a C type",
757 i);
758 return -1;
759 }
760 /*
761 * We need one extra ffi_type to hold the struct, and one
762 * ffi_type pointer per array element + one for a NULL to
763 * mark the end.
764 */
765 num_ffi_types++;
766 num_ffi_type_pointers += length + 1;
767 }
768 Py_DECREF(pair);
769 }
770
771 /*
772 * At this point, we know we need storage for some ffi_types and some
773 * ffi_type pointers. We'll allocate these in one block.
774 * There are three sub-blocks of information: the ffi_type pointers to
775 * this structure/union's elements, the ffi_type_pointers to the
776 * dummy fields standing in for array elements, and the
777 * ffi_types representing the dummy structures.
778 */
779 alloc_size = (ffi_ofs + 1 + len + num_ffi_type_pointers) * sizeof(ffi_type *) +
780 num_ffi_types * sizeof(ffi_type);
781 type_block = PyMem_Malloc(alloc_size);
782
783 if (type_block == NULL) {
784 PyErr_NoMemory();
785 return -1;
786 }
787 /*
788 * the first block takes up ffi_ofs + len + 1 which is the pointers *
789 * for this struct/union. The second block takes up
790 * num_ffi_type_pointers, so the sum of these is ffi_ofs + len + 1 +
791 * num_ffi_type_pointers as allocated above. The last bit is the
792 * num_ffi_types structs.
793 */
794 element_types = (ffi_type **) type_block;
795 dummy_types = &element_types[ffi_ofs + len + 1];
796 structs = (ffi_type *) &dummy_types[num_ffi_type_pointers];
797
798 if (num_ffi_types > 0) {
799 memset(structs, 0, num_ffi_types * sizeof(ffi_type));
800 }
801 if (ffi_ofs && (basedict != NULL)) {
802 memcpy(element_types,
803 basedict->ffi_type_pointer.elements,
804 ffi_ofs * sizeof(ffi_type *));
805 }
806 element_index = ffi_ofs;
807
808 /* second pass to actually set the type pointers */
809 for (i = 0; i < len; ++i) {
810 PyObject *name, *desc;
811 PyObject *pair = PySequence_GetItem(fields, i);
812 StgDictObject *dict;
813 int bitsize = 0;
814
815 if (pair == NULL) {
816 PyMem_Free(type_block);
817 return -1;
818 }
819 /* In theory, we made this call in the first pass, so it *shouldn't*
820 * fail. However, you never know, and the code above might change
821 * later - keeping the check in here is a tad defensive but it
822 * will affect program size only slightly and performance hardly at
823 * all.
824 */
825 if (!PyArg_ParseTuple(pair, "UO|i", &name, &desc, &bitsize)) {
826 PyErr_SetString(PyExc_TypeError,
827 "'_fields_' must be a sequence of (name, C type) pairs");
828 Py_DECREF(pair);
829 PyMem_Free(type_block);
830 return -1;
831 }
832 dict = PyType_stgdict(desc);
833 /* Possibly this check could be avoided, but see above comment. */
834 if (dict == NULL) {
835 Py_DECREF(pair);
836 PyMem_Free(type_block);
837 PyErr_Format(PyExc_TypeError,
838 "second item in _fields_ tuple (index %zd) must be a C type",
839 i);
840 return -1;
841 }
842 assert(element_index < (ffi_ofs + len)); /* will be used below */
843 if (!PyCArrayTypeObject_Check(desc)) {
844 /* Not an array. Just copy over the element ffi_type. */
845 element_types[element_index++] = &dict->ffi_type_pointer;
846 }
847 else {
848 Py_ssize_t length = dict->length;
849 StgDictObject *edict;
850
851 edict = PyType_stgdict(dict->proto);
852 if (edict == NULL) {
853 Py_DECREF(pair);
854 PyMem_Free(type_block);
855 PyErr_Format(PyExc_TypeError,
856 "second item in _fields_ tuple (index %zd) must be a C type",
857 i);
858 return -1;
859 }
860 element_types[element_index++] = &structs[struct_index];
861 structs[struct_index].size = length * edict->ffi_type_pointer.size;
862 structs[struct_index].alignment = edict->ffi_type_pointer.alignment;
863 structs[struct_index].type = FFI_TYPE_STRUCT;
864 structs[struct_index].elements = &dummy_types[dummy_index];
865 ++struct_index;
866 /* Copy over the element's type, length times. */
867 while (length > 0) {
868 assert(dummy_index < (num_ffi_type_pointers));
869 dummy_types[dummy_index++] = &edict->ffi_type_pointer;
870 length--;
871 }
872 assert(dummy_index < (num_ffi_type_pointers));
873 dummy_types[dummy_index++] = NULL;
874 }
875 Py_DECREF(pair);
876 }
877
878 element_types[element_index] = NULL;
879 /*
880 * Replace the old elements with the new, taking into account
881 * base class elements where necessary.
882 */
883 assert(stgdict->ffi_type_pointer.elements);
884 PyMem_Free(stgdict->ffi_type_pointer.elements);
885 stgdict->ffi_type_pointer.elements = element_types;
886 }
887
888 /* We did check that this flag was NOT set above, it must not
889 have been set until now. */
890 if (stgdict->flags & DICTFLAG_FINAL) {
891 PyErr_SetString(PyExc_AttributeError,
892 "Structure or union cannot contain itself");
893 return -1;
894 }
895 stgdict->flags |= DICTFLAG_FINAL;
896
897 return MakeAnonFields(type);
898 }
899