blob: 25d999626a1cab044c31a9c39c22593da91db5b9 [file] [log] [blame]
Thomas Hellerd4c93202006-03-08 19:35:11 +00001#include "Python.h"
2#include <ffi.h>
3#ifdef MS_WIN32
4#include <windows.h>
Thomas Hellerb041fda2008-04-30 17:11:46 +00005#include <malloc.h>
Thomas Hellerd4c93202006-03-08 19:35:11 +00006#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 */
19static int
Thomas Heller34596a92009-04-24 20:50:00 +000020PyCStgDict_init(StgDictObject *self, PyObject *args, PyObject *kwds)
Thomas Hellerd4c93202006-03-08 19:35:11 +000021{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000022 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;
Thomas Hellerd4c93202006-03-08 19:35:11 +000028}
29
30static int
Thomas Heller34596a92009-04-24 20:50:00 +000031PyCStgDict_clear(StgDictObject *self)
Thomas Hellerd4c93202006-03-08 19:35:11 +000032{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000033 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;
Thomas Hellerd4c93202006-03-08 19:35:11 +000039}
40
41static void
Thomas Heller34596a92009-04-24 20:50:00 +000042PyCStgDict_dealloc(StgDictObject *self)
Thomas Hellerd4c93202006-03-08 19:35:11 +000043{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000044 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);
Thomas Hellerd4c93202006-03-08 19:35:11 +000049}
50
51int
Thomas Heller34596a92009-04-24 20:50:00 +000052PyCStgDict_clone(StgDictObject *dst, StgDictObject *src)
Thomas Hellerd4c93202006-03-08 19:35:11 +000053{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000054 char *d, *s;
55 Py_ssize_t size;
Thomas Hellerd4c93202006-03-08 19:35:11 +000056
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000057 PyCStgDict_clear(dst);
58 PyMem_Free(dst->ffi_type_pointer.elements);
59 PyMem_Free(dst->format);
60 dst->format = NULL;
61 PyMem_Free(dst->shape);
62 dst->shape = NULL;
63 dst->ffi_type_pointer.elements = NULL;
Thomas Hellerd4c93202006-03-08 19:35:11 +000064
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000065 d = (char *)dst;
66 s = (char *)src;
67 memcpy(d + sizeof(PyDictObject),
68 s + sizeof(PyDictObject),
69 sizeof(StgDictObject) - sizeof(PyDictObject));
Thomas Hellerd4c93202006-03-08 19:35:11 +000070
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000071 Py_XINCREF(dst->proto);
72 Py_XINCREF(dst->argtypes);
73 Py_XINCREF(dst->converters);
74 Py_XINCREF(dst->restype);
75 Py_XINCREF(dst->checker);
Thomas Hellerd4c93202006-03-08 19:35:11 +000076
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000077 if (src->format) {
78 dst->format = PyMem_Malloc(strlen(src->format) + 1);
79 if (dst->format == NULL)
80 return -1;
81 strcpy(dst->format, src->format);
82 }
83 if (src->shape) {
84 dst->shape = PyMem_Malloc(sizeof(Py_ssize_t) * src->ndim);
85 if (dst->shape == NULL)
86 return -1;
87 memcpy(dst->shape, src->shape,
88 sizeof(Py_ssize_t) * src->ndim);
89 }
Thomas Hellerb041fda2008-04-30 17:11:46 +000090
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000091 if (src->ffi_type_pointer.elements == NULL)
92 return 0;
93 size = sizeof(ffi_type *) * (src->length + 1);
94 dst->ffi_type_pointer.elements = PyMem_Malloc(size);
95 if (dst->ffi_type_pointer.elements == NULL) {
96 PyErr_NoMemory();
97 return -1;
98 }
99 memcpy(dst->ffi_type_pointer.elements,
100 src->ffi_type_pointer.elements,
101 size);
102 return 0;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000103}
104
Thomas Heller34596a92009-04-24 20:50:00 +0000105PyTypeObject PyCStgDict_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000106 PyVarObject_HEAD_INIT(NULL, 0)
107 "StgDict",
108 sizeof(StgDictObject),
109 0,
110 (destructor)PyCStgDict_dealloc, /* tp_dealloc */
111 0, /* tp_print */
112 0, /* tp_getattr */
113 0, /* tp_setattr */
114 0, /* tp_reserved */
115 0, /* tp_repr */
116 0, /* tp_as_number */
117 0, /* tp_as_sequence */
118 0, /* tp_as_mapping */
119 0, /* tp_hash */
120 0, /* tp_call */
121 0, /* tp_str */
122 0, /* tp_getattro */
123 0, /* tp_setattro */
124 0, /* tp_as_buffer */
125 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
126 0, /* tp_doc */
127 0, /* tp_traverse */
128 0, /* tp_clear */
129 0, /* tp_richcompare */
130 0, /* tp_weaklistoffset */
131 0, /* tp_iter */
132 0, /* tp_iternext */
133 0, /* tp_methods */
134 0, /* tp_members */
135 0, /* tp_getset */
136 0, /* tp_base */
137 0, /* tp_dict */
138 0, /* tp_descr_get */
139 0, /* tp_descr_set */
140 0, /* tp_dictoffset */
141 (initproc)PyCStgDict_init, /* tp_init */
142 0, /* tp_alloc */
143 0, /* tp_new */
144 0, /* tp_free */
Thomas Hellerd4c93202006-03-08 19:35:11 +0000145};
146
147/* May return NULL, but does not set an exception! */
148StgDictObject *
149PyType_stgdict(PyObject *obj)
150{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000151 PyTypeObject *type;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000152
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000153 if (!PyType_Check(obj))
154 return NULL;
155 type = (PyTypeObject *)obj;
156 if (!type->tp_dict || !PyCStgDict_CheckExact(type->tp_dict))
157 return NULL;
158 return (StgDictObject *)type->tp_dict;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000159}
160
161/* May return NULL, but does not set an exception! */
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000162/*
163 This function should be as fast as possible, so we don't call PyType_stgdict
164 above but inline the code, and avoid the PyType_Check().
165*/
Thomas Hellerd4c93202006-03-08 19:35:11 +0000166StgDictObject *
167PyObject_stgdict(PyObject *self)
168{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000169 PyTypeObject *type = self->ob_type;
170 if (!type->tp_dict || !PyCStgDict_CheckExact(type->tp_dict))
171 return NULL;
172 return (StgDictObject *)type->tp_dict;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000173}
174
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000175/* descr is the descriptor for a field marked as anonymous. Get all the
176 _fields_ descriptors from descr->proto, create new descriptors with offset
177 and index adjusted, and stuff them into type.
178 */
179static int
180MakeFields(PyObject *type, CFieldObject *descr,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000181 Py_ssize_t index, Py_ssize_t offset)
Thomas Hellerd4c93202006-03-08 19:35:11 +0000182{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000183 Py_ssize_t i;
184 PyObject *fields;
185 PyObject *fieldlist;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000186
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000187 fields = PyObject_GetAttrString(descr->proto, "_fields_");
188 if (fields == NULL)
189 return -1;
190 fieldlist = PySequence_Fast(fields, "_fields_ must be a sequence");
191 Py_DECREF(fields);
192 if (fieldlist == NULL)
193 return -1;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000194
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000195 for (i = 0; i < PySequence_Fast_GET_SIZE(fieldlist); ++i) {
196 PyObject *pair = PySequence_Fast_GET_ITEM(fieldlist, i); /* borrowed */
197 PyObject *fname, *ftype, *bits;
198 CFieldObject *fdescr;
199 CFieldObject *new_descr;
200 /* Convert to PyArg_UnpackTuple... */
201 if (!PyArg_ParseTuple(pair, "OO|O", &fname, &ftype, &bits)) {
202 Py_DECREF(fieldlist);
203 return -1;
204 }
205 fdescr = (CFieldObject *)PyObject_GetAttr(descr->proto, fname);
206 if (fdescr == NULL) {
207 Py_DECREF(fieldlist);
208 return -1;
209 }
210 if (Py_TYPE(fdescr) != &PyCField_Type) {
211 PyErr_SetString(PyExc_TypeError, "unexpected type");
212 Py_DECREF(fdescr);
213 Py_DECREF(fieldlist);
214 return -1;
215 }
216 if (fdescr->anonymous) {
217 int rc = MakeFields(type, fdescr,
218 index + fdescr->index,
219 offset + fdescr->offset);
220 Py_DECREF(fdescr);
221 if (rc == -1) {
222 Py_DECREF(fieldlist);
223 return -1;
224 }
225 continue;
226 }
227 new_descr = (CFieldObject *)PyObject_CallObject((PyObject *)&PyCField_Type, NULL);
228 if (new_descr == NULL) {
229 Py_DECREF(fdescr);
230 Py_DECREF(fieldlist);
231 return -1;
232 }
233 assert(Py_TYPE(new_descr) == &PyCField_Type);
234 new_descr->size = fdescr->size;
235 new_descr->offset = fdescr->offset + offset;
236 new_descr->index = fdescr->index + index;
237 new_descr->proto = fdescr->proto;
238 Py_XINCREF(new_descr->proto);
239 new_descr->getfunc = fdescr->getfunc;
240 new_descr->setfunc = fdescr->setfunc;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000241
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000242 Py_DECREF(fdescr);
243
244 if (-1 == PyObject_SetAttr(type, fname, (PyObject *)new_descr)) {
245 Py_DECREF(fieldlist);
246 Py_DECREF(new_descr);
247 return -1;
248 }
249 Py_DECREF(new_descr);
250 }
251 Py_DECREF(fieldlist);
252 return 0;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000253}
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000254
255/* Iterate over the names in the type's _anonymous_ attribute, if present,
256 */
257static int
258MakeAnonFields(PyObject *type)
259{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000260 PyObject *anon;
261 PyObject *anon_names;
262 Py_ssize_t i;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000263
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000264 anon = PyObject_GetAttrString(type, "_anonymous_");
265 if (anon == NULL) {
266 PyErr_Clear();
267 return 0;
268 }
269 anon_names = PySequence_Fast(anon, "_anonymous_ must be a sequence");
270 Py_DECREF(anon);
271 if (anon_names == NULL)
272 return -1;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000273
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000274 for (i = 0; i < PySequence_Fast_GET_SIZE(anon_names); ++i) {
275 PyObject *fname = PySequence_Fast_GET_ITEM(anon_names, i); /* borrowed */
276 CFieldObject *descr = (CFieldObject *)PyObject_GetAttr(type, fname);
277 if (descr == NULL) {
278 Py_DECREF(anon_names);
279 return -1;
280 }
281 assert(Py_TYPE(descr) == &PyCField_Type);
282 descr->anonymous = 1;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000283
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000284 /* descr is in the field descriptor. */
285 if (-1 == MakeFields(type, (CFieldObject *)descr,
286 ((CFieldObject *)descr)->index,
287 ((CFieldObject *)descr)->offset)) {
288 Py_DECREF(descr);
289 Py_DECREF(anon_names);
290 return -1;
291 }
292 Py_DECREF(descr);
293 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000294
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000295 Py_DECREF(anon_names);
296 return 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000297}
Thomas Hellerd4c93202006-03-08 19:35:11 +0000298
299/*
300 Retrive the (optional) _pack_ attribute from a type, the _fields_ attribute,
301 and create an StgDictObject. Used for Structure and Union subclasses.
302*/
303int
Thomas Heller34596a92009-04-24 20:50:00 +0000304PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct)
Thomas Hellerd4c93202006-03-08 19:35:11 +0000305{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000306 StgDictObject *stgdict, *basedict;
307 Py_ssize_t len, offset, size, align, i;
308 Py_ssize_t union_size, total_align;
309 Py_ssize_t field_size = 0;
310 int bitofs;
311 PyObject *isPacked;
312 int pack = 0;
313 Py_ssize_t ffi_ofs;
314 int big_endian;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000315
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000316 /* HACK Alert: I cannot be bothered to fix ctypes.com, so there has to
317 be a way to use the old, broken sematics: _fields_ are not extended
318 but replaced in subclasses.
Thomas Hellerd4c93202006-03-08 19:35:11 +0000319
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000320 XXX Remove this in ctypes 1.0!
321 */
322 int use_broken_old_ctypes_semantics;
323
324 if (fields == NULL)
325 return 0;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000326
327#ifdef WORDS_BIGENDIAN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000328 big_endian = PyObject_HasAttrString(type, "_swappedbytes_") ? 0 : 1;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000329#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000330 big_endian = PyObject_HasAttrString(type, "_swappedbytes_") ? 1 : 0;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000331#endif
332
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000333 use_broken_old_ctypes_semantics = \
334 PyObject_HasAttrString(type, "_use_broken_old_ctypes_structure_semantics_");
Thomas Hellerd4c93202006-03-08 19:35:11 +0000335
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000336 isPacked = PyObject_GetAttrString(type, "_pack_");
337 if (isPacked) {
Serhiy Storchaka441d30f2013-01-19 12:26:26 +0200338 pack = _PyLong_AsInt(isPacked);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000339 if (pack < 0 || PyErr_Occurred()) {
340 Py_XDECREF(isPacked);
341 PyErr_SetString(PyExc_ValueError,
342 "_pack_ must be a non-negative integer");
343 return -1;
344 }
345 Py_DECREF(isPacked);
346 } else
347 PyErr_Clear();
Thomas Hellerd4c93202006-03-08 19:35:11 +0000348
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000349 len = PySequence_Length(fields);
350 if (len == -1) {
351 PyErr_SetString(PyExc_TypeError,
352 "'_fields_' must be a sequence of pairs");
353 return -1;
354 }
Thomas Hellerd4c93202006-03-08 19:35:11 +0000355
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000356 stgdict = PyType_stgdict(type);
357 if (!stgdict)
358 return -1;
359 /* If this structure/union is already marked final we cannot assign
360 _fields_ anymore. */
Thomas Wouters89f507f2006-12-13 04:49:30 +0000361
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000362 if (stgdict->flags & DICTFLAG_FINAL) {/* is final ? */
363 PyErr_SetString(PyExc_AttributeError,
364 "_fields_ is final");
365 return -1;
366 }
Thomas Hellerd4c93202006-03-08 19:35:11 +0000367
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000368 if (stgdict->format) {
369 PyMem_Free(stgdict->format);
370 stgdict->format = NULL;
371 }
Thomas Hellerb041fda2008-04-30 17:11:46 +0000372
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000373 if (stgdict->ffi_type_pointer.elements)
374 PyMem_Free(stgdict->ffi_type_pointer.elements);
Thomas Hellerd4c93202006-03-08 19:35:11 +0000375
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000376 basedict = PyType_stgdict((PyObject *)((PyTypeObject *)type)->tp_base);
377 if (basedict && !use_broken_old_ctypes_semantics) {
378 size = offset = basedict->size;
379 align = basedict->align;
380 union_size = 0;
381 total_align = align ? align : 1;
382 stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT;
383 stgdict->ffi_type_pointer.elements = PyMem_Malloc(sizeof(ffi_type *) * (basedict->length + len + 1));
384 if (stgdict->ffi_type_pointer.elements == NULL) {
385 PyErr_NoMemory();
386 return -1;
387 }
388 memset(stgdict->ffi_type_pointer.elements, 0,
389 sizeof(ffi_type *) * (basedict->length + len + 1));
390 memcpy(stgdict->ffi_type_pointer.elements,
391 basedict->ffi_type_pointer.elements,
392 sizeof(ffi_type *) * (basedict->length));
393 ffi_ofs = basedict->length;
394 } else {
395 offset = 0;
396 size = 0;
397 align = 0;
398 union_size = 0;
399 total_align = 1;
400 stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT;
401 stgdict->ffi_type_pointer.elements = PyMem_Malloc(sizeof(ffi_type *) * (len + 1));
402 if (stgdict->ffi_type_pointer.elements == NULL) {
403 PyErr_NoMemory();
404 return -1;
405 }
406 memset(stgdict->ffi_type_pointer.elements, 0,
407 sizeof(ffi_type *) * (len + 1));
408 ffi_ofs = 0;
409 }
Thomas Hellerd4c93202006-03-08 19:35:11 +0000410
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000411 assert(stgdict->format == NULL);
412 if (isStruct && !isPacked) {
413 stgdict->format = _ctypes_alloc_format_string(NULL, "T{");
414 } else {
415 /* PEP3118 doesn't support union, or packed structures (well,
416 only standard packing, but we dont support the pep for
417 that). Use 'B' for bytes. */
418 stgdict->format = _ctypes_alloc_format_string(NULL, "B");
419 }
Thomas Hellerb041fda2008-04-30 17:11:46 +0000420
Thomas Hellerd4c93202006-03-08 19:35:11 +0000421#define realdict ((PyObject *)&stgdict->dict)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000422 for (i = 0; i < len; ++i) {
423 PyObject *name = NULL, *desc = NULL;
424 PyObject *pair = PySequence_GetItem(fields, i);
425 PyObject *prop;
426 StgDictObject *dict;
427 int bitsize = 0;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000428
Amaury Forgeot d'Arc842d9212011-09-02 23:07:54 +0200429 if (!pair || !PyArg_ParseTuple(pair, "UO|i", &name, &desc, &bitsize)) {
430 PyErr_SetString(PyExc_TypeError,
431 "'_fields_' must be a sequence of (name, C type) pairs");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000432 Py_XDECREF(pair);
433 return -1;
434 }
435 dict = PyType_stgdict(desc);
436 if (dict == NULL) {
437 Py_DECREF(pair);
438 PyErr_Format(PyExc_TypeError,
439 "second item in _fields_ tuple (index %zd) must be a C type",
440 i);
441 return -1;
442 }
443 stgdict->ffi_type_pointer.elements[ffi_ofs + i] = &dict->ffi_type_pointer;
444 if (dict->flags & (TYPEFLAG_ISPOINTER | TYPEFLAG_HASPOINTER))
445 stgdict->flags |= TYPEFLAG_HASPOINTER;
446 dict->flags |= DICTFLAG_FINAL; /* mark field type final */
447 if (PyTuple_Size(pair) == 3) { /* bits specified */
448 switch(dict->ffi_type_pointer.type) {
449 case FFI_TYPE_UINT8:
450 case FFI_TYPE_UINT16:
451 case FFI_TYPE_UINT32:
452 case FFI_TYPE_SINT64:
453 case FFI_TYPE_UINT64:
454 break;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000455
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000456 case FFI_TYPE_SINT8:
457 case FFI_TYPE_SINT16:
458 case FFI_TYPE_SINT32:
459 if (dict->getfunc != _ctypes_get_fielddesc("c")->getfunc
Thomas Hellerd4c93202006-03-08 19:35:11 +0000460#ifdef CTYPES_UNICODE
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000461 && dict->getfunc != _ctypes_get_fielddesc("u")->getfunc
Thomas Hellerd4c93202006-03-08 19:35:11 +0000462#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000463 )
464 break;
465 /* else fall through */
466 default:
467 PyErr_Format(PyExc_TypeError,
468 "bit fields not allowed for type %s",
469 ((PyTypeObject *)desc)->tp_name);
470 Py_DECREF(pair);
471 return -1;
472 }
473 if (bitsize <= 0 || bitsize > dict->size * 8) {
474 PyErr_SetString(PyExc_ValueError,
475 "number of bits invalid for bit field");
476 Py_DECREF(pair);
477 return -1;
478 }
479 } else
480 bitsize = 0;
Amaury Forgeot d'Arc842d9212011-09-02 23:07:54 +0200481
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000482 if (isStruct && !isPacked) {
483 char *fieldfmt = dict->format ? dict->format : "B";
484 char *fieldname = _PyUnicode_AsString(name);
485 char *ptr;
Amaury Forgeot d'Arc02dd5392011-09-02 20:39:40 +0200486 Py_ssize_t len;
487 char *buf;
488
489 if (fieldname == NULL)
490 {
Amaury Forgeot d'Arc02dd5392011-09-02 20:39:40 +0200491 Py_DECREF(pair);
492 return -1;
493 }
494
495 len = strlen(fieldname) + strlen(fieldfmt);
Thomas Hellerb041fda2008-04-30 17:11:46 +0000496
Meador Inge1efb33a2011-10-03 21:44:22 -0500497 buf = PyMem_Malloc(len + 2 + 1);
498 if (buf == NULL) {
499 Py_DECREF(pair);
500 PyErr_NoMemory();
501 return -1;
502 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000503 sprintf(buf, "%s:%s:", fieldfmt, fieldname);
Thomas Hellerb041fda2008-04-30 17:11:46 +0000504
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000505 ptr = stgdict->format;
506 stgdict->format = _ctypes_alloc_format_string(stgdict->format, buf);
507 PyMem_Free(ptr);
Meador Inge1efb33a2011-10-03 21:44:22 -0500508 PyMem_Free(buf);
Thomas Hellerb041fda2008-04-30 17:11:46 +0000509
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000510 if (stgdict->format == NULL) {
511 Py_DECREF(pair);
512 return -1;
513 }
514 }
Amaury Forgeot d'Arc842d9212011-09-02 23:07:54 +0200515
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000516 if (isStruct) {
517 prop = PyCField_FromDesc(desc, i,
518 &field_size, bitsize, &bitofs,
519 &size, &offset, &align,
520 pack, big_endian);
521 } else /* union */ {
522 size = 0;
523 offset = 0;
524 align = 0;
525 prop = PyCField_FromDesc(desc, i,
526 &field_size, bitsize, &bitofs,
527 &size, &offset, &align,
528 pack, big_endian);
529 union_size = max(size, union_size);
530 }
531 total_align = max(align, total_align);
Thomas Hellerd4c93202006-03-08 19:35:11 +0000532
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000533 if (!prop) {
534 Py_DECREF(pair);
535 return -1;
536 }
537 if (-1 == PyObject_SetAttr(type, name, prop)) {
538 Py_DECREF(prop);
539 Py_DECREF(pair);
540 return -1;
541 }
542 Py_DECREF(pair);
543 Py_DECREF(prop);
544 }
Thomas Hellerd4c93202006-03-08 19:35:11 +0000545#undef realdict
Thomas Hellerb041fda2008-04-30 17:11:46 +0000546
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000547 if (isStruct && !isPacked) {
548 char *ptr = stgdict->format;
549 stgdict->format = _ctypes_alloc_format_string(stgdict->format, "}");
550 PyMem_Free(ptr);
551 if (stgdict->format == NULL)
552 return -1;
553 }
Thomas Hellerb041fda2008-04-30 17:11:46 +0000554
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000555 if (!isStruct)
556 size = union_size;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000557
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000558 /* Adjust the size according to the alignment requirements */
559 size = ((size + total_align - 1) / total_align) * total_align;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000560
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000561 stgdict->ffi_type_pointer.alignment = Py_SAFE_DOWNCAST(total_align,
562 Py_ssize_t,
563 unsigned short);
564 stgdict->ffi_type_pointer.size = size;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000565
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000566 stgdict->size = size;
567 stgdict->align = total_align;
568 stgdict->length = len; /* ADD ffi_ofs? */
Thomas Wouters89f507f2006-12-13 04:49:30 +0000569
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000570 /* We did check that this flag was NOT set above, it must not
571 have been set until now. */
572 if (stgdict->flags & DICTFLAG_FINAL) {
573 PyErr_SetString(PyExc_AttributeError,
574 "Structure or union cannot contain itself");
575 return -1;
576 }
577 stgdict->flags |= DICTFLAG_FINAL;
Thomas Wouters89f507f2006-12-13 04:49:30 +0000578
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000579 return MakeAnonFields(type);
Thomas Hellerd4c93202006-03-08 19:35:11 +0000580}