1 | n/a | #include "Python.h" |
---|
2 | n/a | #include <ffi.h> |
---|
3 | n/a | #ifdef MS_WIN32 |
---|
4 | n/a | #include <windows.h> |
---|
5 | n/a | #include <malloc.h> |
---|
6 | n/a | #endif |
---|
7 | n/a | #include "ctypes.h" |
---|
8 | n/a | |
---|
9 | n/a | /******************************************************************/ |
---|
10 | n/a | /* |
---|
11 | n/a | StdDict - a dictionary subclass, containing additional C accessible fields |
---|
12 | n/a | |
---|
13 | n/a | XXX blabla more |
---|
14 | n/a | */ |
---|
15 | n/a | |
---|
16 | n/a | /* Seems we need this, otherwise we get problems when calling |
---|
17 | n/a | * PyDict_SetItem() (ma_lookup is NULL) |
---|
18 | n/a | */ |
---|
19 | n/a | static int |
---|
20 | n/a | PyCStgDict_init(StgDictObject *self, PyObject *args, PyObject *kwds) |
---|
21 | n/a | { |
---|
22 | n/a | if (PyDict_Type.tp_init((PyObject *)self, args, kwds) < 0) |
---|
23 | n/a | return -1; |
---|
24 | n/a | self->format = NULL; |
---|
25 | n/a | self->ndim = 0; |
---|
26 | n/a | self->shape = NULL; |
---|
27 | n/a | return 0; |
---|
28 | n/a | } |
---|
29 | n/a | |
---|
30 | n/a | static int |
---|
31 | n/a | PyCStgDict_clear(StgDictObject *self) |
---|
32 | n/a | { |
---|
33 | n/a | Py_CLEAR(self->proto); |
---|
34 | n/a | Py_CLEAR(self->argtypes); |
---|
35 | n/a | Py_CLEAR(self->converters); |
---|
36 | n/a | Py_CLEAR(self->restype); |
---|
37 | n/a | Py_CLEAR(self->checker); |
---|
38 | n/a | return 0; |
---|
39 | n/a | } |
---|
40 | n/a | |
---|
41 | n/a | static void |
---|
42 | n/a | PyCStgDict_dealloc(StgDictObject *self) |
---|
43 | n/a | { |
---|
44 | n/a | PyCStgDict_clear(self); |
---|
45 | n/a | PyMem_Free(self->format); |
---|
46 | n/a | PyMem_Free(self->shape); |
---|
47 | n/a | PyMem_Free(self->ffi_type_pointer.elements); |
---|
48 | n/a | PyDict_Type.tp_dealloc((PyObject *)self); |
---|
49 | n/a | } |
---|
50 | n/a | |
---|
51 | n/a | int |
---|
52 | n/a | PyCStgDict_clone(StgDictObject *dst, StgDictObject *src) |
---|
53 | n/a | { |
---|
54 | n/a | char *d, *s; |
---|
55 | n/a | Py_ssize_t size; |
---|
56 | n/a | |
---|
57 | n/a | PyCStgDict_clear(dst); |
---|
58 | n/a | PyMem_Free(dst->ffi_type_pointer.elements); |
---|
59 | n/a | PyMem_Free(dst->format); |
---|
60 | n/a | dst->format = NULL; |
---|
61 | n/a | PyMem_Free(dst->shape); |
---|
62 | n/a | dst->shape = NULL; |
---|
63 | n/a | dst->ffi_type_pointer.elements = NULL; |
---|
64 | n/a | |
---|
65 | n/a | d = (char *)dst; |
---|
66 | n/a | s = (char *)src; |
---|
67 | n/a | memcpy(d + sizeof(PyDictObject), |
---|
68 | n/a | s + sizeof(PyDictObject), |
---|
69 | n/a | sizeof(StgDictObject) - sizeof(PyDictObject)); |
---|
70 | n/a | |
---|
71 | n/a | Py_XINCREF(dst->proto); |
---|
72 | n/a | Py_XINCREF(dst->argtypes); |
---|
73 | n/a | Py_XINCREF(dst->converters); |
---|
74 | n/a | Py_XINCREF(dst->restype); |
---|
75 | n/a | Py_XINCREF(dst->checker); |
---|
76 | n/a | |
---|
77 | n/a | if (src->format) { |
---|
78 | n/a | dst->format = PyMem_Malloc(strlen(src->format) + 1); |
---|
79 | n/a | if (dst->format == NULL) { |
---|
80 | n/a | PyErr_NoMemory(); |
---|
81 | n/a | return -1; |
---|
82 | n/a | } |
---|
83 | n/a | strcpy(dst->format, src->format); |
---|
84 | n/a | } |
---|
85 | n/a | if (src->shape) { |
---|
86 | n/a | dst->shape = PyMem_Malloc(sizeof(Py_ssize_t) * src->ndim); |
---|
87 | n/a | if (dst->shape == NULL) { |
---|
88 | n/a | PyErr_NoMemory(); |
---|
89 | n/a | return -1; |
---|
90 | n/a | } |
---|
91 | n/a | memcpy(dst->shape, src->shape, |
---|
92 | n/a | sizeof(Py_ssize_t) * src->ndim); |
---|
93 | n/a | } |
---|
94 | n/a | |
---|
95 | n/a | if (src->ffi_type_pointer.elements == NULL) |
---|
96 | n/a | return 0; |
---|
97 | n/a | size = sizeof(ffi_type *) * (src->length + 1); |
---|
98 | n/a | dst->ffi_type_pointer.elements = PyMem_Malloc(size); |
---|
99 | n/a | if (dst->ffi_type_pointer.elements == NULL) { |
---|
100 | n/a | PyErr_NoMemory(); |
---|
101 | n/a | return -1; |
---|
102 | n/a | } |
---|
103 | n/a | memcpy(dst->ffi_type_pointer.elements, |
---|
104 | n/a | src->ffi_type_pointer.elements, |
---|
105 | n/a | size); |
---|
106 | n/a | return 0; |
---|
107 | n/a | } |
---|
108 | n/a | |
---|
109 | n/a | PyTypeObject PyCStgDict_Type = { |
---|
110 | n/a | PyVarObject_HEAD_INIT(NULL, 0) |
---|
111 | n/a | "StgDict", |
---|
112 | n/a | sizeof(StgDictObject), |
---|
113 | n/a | 0, |
---|
114 | n/a | (destructor)PyCStgDict_dealloc, /* tp_dealloc */ |
---|
115 | n/a | 0, /* tp_print */ |
---|
116 | n/a | 0, /* tp_getattr */ |
---|
117 | n/a | 0, /* tp_setattr */ |
---|
118 | n/a | 0, /* tp_reserved */ |
---|
119 | n/a | 0, /* tp_repr */ |
---|
120 | n/a | 0, /* tp_as_number */ |
---|
121 | n/a | 0, /* tp_as_sequence */ |
---|
122 | n/a | 0, /* tp_as_mapping */ |
---|
123 | n/a | 0, /* tp_hash */ |
---|
124 | n/a | 0, /* tp_call */ |
---|
125 | n/a | 0, /* tp_str */ |
---|
126 | n/a | 0, /* tp_getattro */ |
---|
127 | n/a | 0, /* tp_setattro */ |
---|
128 | n/a | 0, /* tp_as_buffer */ |
---|
129 | n/a | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ |
---|
130 | n/a | 0, /* tp_doc */ |
---|
131 | n/a | 0, /* tp_traverse */ |
---|
132 | n/a | 0, /* tp_clear */ |
---|
133 | n/a | 0, /* tp_richcompare */ |
---|
134 | n/a | 0, /* tp_weaklistoffset */ |
---|
135 | n/a | 0, /* tp_iter */ |
---|
136 | n/a | 0, /* tp_iternext */ |
---|
137 | n/a | 0, /* tp_methods */ |
---|
138 | n/a | 0, /* tp_members */ |
---|
139 | n/a | 0, /* tp_getset */ |
---|
140 | n/a | 0, /* tp_base */ |
---|
141 | n/a | 0, /* tp_dict */ |
---|
142 | n/a | 0, /* tp_descr_get */ |
---|
143 | n/a | 0, /* tp_descr_set */ |
---|
144 | n/a | 0, /* tp_dictoffset */ |
---|
145 | n/a | (initproc)PyCStgDict_init, /* tp_init */ |
---|
146 | n/a | 0, /* tp_alloc */ |
---|
147 | n/a | 0, /* tp_new */ |
---|
148 | n/a | 0, /* tp_free */ |
---|
149 | n/a | }; |
---|
150 | n/a | |
---|
151 | n/a | /* May return NULL, but does not set an exception! */ |
---|
152 | n/a | StgDictObject * |
---|
153 | n/a | PyType_stgdict(PyObject *obj) |
---|
154 | n/a | { |
---|
155 | n/a | PyTypeObject *type; |
---|
156 | n/a | |
---|
157 | n/a | if (!PyType_Check(obj)) |
---|
158 | n/a | return NULL; |
---|
159 | n/a | type = (PyTypeObject *)obj; |
---|
160 | n/a | if (!type->tp_dict || !PyCStgDict_CheckExact(type->tp_dict)) |
---|
161 | n/a | return NULL; |
---|
162 | n/a | return (StgDictObject *)type->tp_dict; |
---|
163 | n/a | } |
---|
164 | n/a | |
---|
165 | n/a | /* May return NULL, but does not set an exception! */ |
---|
166 | n/a | /* |
---|
167 | n/a | This function should be as fast as possible, so we don't call PyType_stgdict |
---|
168 | n/a | above but inline the code, and avoid the PyType_Check(). |
---|
169 | n/a | */ |
---|
170 | n/a | StgDictObject * |
---|
171 | n/a | PyObject_stgdict(PyObject *self) |
---|
172 | n/a | { |
---|
173 | n/a | PyTypeObject *type = self->ob_type; |
---|
174 | n/a | if (!type->tp_dict || !PyCStgDict_CheckExact(type->tp_dict)) |
---|
175 | n/a | return NULL; |
---|
176 | n/a | return (StgDictObject *)type->tp_dict; |
---|
177 | n/a | } |
---|
178 | n/a | |
---|
179 | n/a | /* descr is the descriptor for a field marked as anonymous. Get all the |
---|
180 | n/a | _fields_ descriptors from descr->proto, create new descriptors with offset |
---|
181 | n/a | and index adjusted, and stuff them into type. |
---|
182 | n/a | */ |
---|
183 | n/a | static int |
---|
184 | n/a | MakeFields(PyObject *type, CFieldObject *descr, |
---|
185 | n/a | Py_ssize_t index, Py_ssize_t offset) |
---|
186 | n/a | { |
---|
187 | n/a | Py_ssize_t i; |
---|
188 | n/a | PyObject *fields; |
---|
189 | n/a | PyObject *fieldlist; |
---|
190 | n/a | |
---|
191 | n/a | fields = PyObject_GetAttrString(descr->proto, "_fields_"); |
---|
192 | n/a | if (fields == NULL) |
---|
193 | n/a | return -1; |
---|
194 | n/a | fieldlist = PySequence_Fast(fields, "_fields_ must be a sequence"); |
---|
195 | n/a | Py_DECREF(fields); |
---|
196 | n/a | if (fieldlist == NULL) |
---|
197 | n/a | return -1; |
---|
198 | n/a | |
---|
199 | n/a | for (i = 0; i < PySequence_Fast_GET_SIZE(fieldlist); ++i) { |
---|
200 | n/a | PyObject *pair = PySequence_Fast_GET_ITEM(fieldlist, i); /* borrowed */ |
---|
201 | n/a | PyObject *fname, *ftype, *bits; |
---|
202 | n/a | CFieldObject *fdescr; |
---|
203 | n/a | CFieldObject *new_descr; |
---|
204 | n/a | /* Convert to PyArg_UnpackTuple... */ |
---|
205 | n/a | if (!PyArg_ParseTuple(pair, "OO|O", &fname, &ftype, &bits)) { |
---|
206 | n/a | Py_DECREF(fieldlist); |
---|
207 | n/a | return -1; |
---|
208 | n/a | } |
---|
209 | n/a | fdescr = (CFieldObject *)PyObject_GetAttr(descr->proto, fname); |
---|
210 | n/a | if (fdescr == NULL) { |
---|
211 | n/a | Py_DECREF(fieldlist); |
---|
212 | n/a | return -1; |
---|
213 | n/a | } |
---|
214 | n/a | if (Py_TYPE(fdescr) != &PyCField_Type) { |
---|
215 | n/a | PyErr_SetString(PyExc_TypeError, "unexpected type"); |
---|
216 | n/a | Py_DECREF(fdescr); |
---|
217 | n/a | Py_DECREF(fieldlist); |
---|
218 | n/a | return -1; |
---|
219 | n/a | } |
---|
220 | n/a | if (fdescr->anonymous) { |
---|
221 | n/a | int rc = MakeFields(type, fdescr, |
---|
222 | n/a | index + fdescr->index, |
---|
223 | n/a | offset + fdescr->offset); |
---|
224 | n/a | Py_DECREF(fdescr); |
---|
225 | n/a | if (rc == -1) { |
---|
226 | n/a | Py_DECREF(fieldlist); |
---|
227 | n/a | return -1; |
---|
228 | n/a | } |
---|
229 | n/a | continue; |
---|
230 | n/a | } |
---|
231 | n/a | new_descr = (CFieldObject *)_PyObject_CallNoArg((PyObject *)&PyCField_Type); |
---|
232 | n/a | if (new_descr == NULL) { |
---|
233 | n/a | Py_DECREF(fdescr); |
---|
234 | n/a | Py_DECREF(fieldlist); |
---|
235 | n/a | return -1; |
---|
236 | n/a | } |
---|
237 | n/a | assert(Py_TYPE(new_descr) == &PyCField_Type); |
---|
238 | n/a | new_descr->size = fdescr->size; |
---|
239 | n/a | new_descr->offset = fdescr->offset + offset; |
---|
240 | n/a | new_descr->index = fdescr->index + index; |
---|
241 | n/a | new_descr->proto = fdescr->proto; |
---|
242 | n/a | Py_XINCREF(new_descr->proto); |
---|
243 | n/a | new_descr->getfunc = fdescr->getfunc; |
---|
244 | n/a | new_descr->setfunc = fdescr->setfunc; |
---|
245 | n/a | |
---|
246 | n/a | Py_DECREF(fdescr); |
---|
247 | n/a | |
---|
248 | n/a | if (-1 == PyObject_SetAttr(type, fname, (PyObject *)new_descr)) { |
---|
249 | n/a | Py_DECREF(fieldlist); |
---|
250 | n/a | Py_DECREF(new_descr); |
---|
251 | n/a | return -1; |
---|
252 | n/a | } |
---|
253 | n/a | Py_DECREF(new_descr); |
---|
254 | n/a | } |
---|
255 | n/a | Py_DECREF(fieldlist); |
---|
256 | n/a | return 0; |
---|
257 | n/a | } |
---|
258 | n/a | |
---|
259 | n/a | /* Iterate over the names in the type's _anonymous_ attribute, if present, |
---|
260 | n/a | */ |
---|
261 | n/a | static int |
---|
262 | n/a | MakeAnonFields(PyObject *type) |
---|
263 | n/a | { |
---|
264 | n/a | PyObject *anon; |
---|
265 | n/a | PyObject *anon_names; |
---|
266 | n/a | Py_ssize_t i; |
---|
267 | n/a | |
---|
268 | n/a | anon = PyObject_GetAttrString(type, "_anonymous_"); |
---|
269 | n/a | if (anon == NULL) { |
---|
270 | n/a | PyErr_Clear(); |
---|
271 | n/a | return 0; |
---|
272 | n/a | } |
---|
273 | n/a | anon_names = PySequence_Fast(anon, "_anonymous_ must be a sequence"); |
---|
274 | n/a | Py_DECREF(anon); |
---|
275 | n/a | if (anon_names == NULL) |
---|
276 | n/a | return -1; |
---|
277 | n/a | |
---|
278 | n/a | for (i = 0; i < PySequence_Fast_GET_SIZE(anon_names); ++i) { |
---|
279 | n/a | PyObject *fname = PySequence_Fast_GET_ITEM(anon_names, i); /* borrowed */ |
---|
280 | n/a | CFieldObject *descr = (CFieldObject *)PyObject_GetAttr(type, fname); |
---|
281 | n/a | if (descr == NULL) { |
---|
282 | n/a | Py_DECREF(anon_names); |
---|
283 | n/a | return -1; |
---|
284 | n/a | } |
---|
285 | n/a | assert(Py_TYPE(descr) == &PyCField_Type); |
---|
286 | n/a | descr->anonymous = 1; |
---|
287 | n/a | |
---|
288 | n/a | /* descr is in the field descriptor. */ |
---|
289 | n/a | if (-1 == MakeFields(type, (CFieldObject *)descr, |
---|
290 | n/a | ((CFieldObject *)descr)->index, |
---|
291 | n/a | ((CFieldObject *)descr)->offset)) { |
---|
292 | n/a | Py_DECREF(descr); |
---|
293 | n/a | Py_DECREF(anon_names); |
---|
294 | n/a | return -1; |
---|
295 | n/a | } |
---|
296 | n/a | Py_DECREF(descr); |
---|
297 | n/a | } |
---|
298 | n/a | |
---|
299 | n/a | Py_DECREF(anon_names); |
---|
300 | n/a | return 0; |
---|
301 | n/a | } |
---|
302 | n/a | |
---|
303 | n/a | /* |
---|
304 | n/a | Retrive the (optional) _pack_ attribute from a type, the _fields_ attribute, |
---|
305 | n/a | and create an StgDictObject. Used for Structure and Union subclasses. |
---|
306 | n/a | */ |
---|
307 | n/a | int |
---|
308 | n/a | PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct) |
---|
309 | n/a | { |
---|
310 | n/a | StgDictObject *stgdict, *basedict; |
---|
311 | n/a | Py_ssize_t len, offset, size, align, i; |
---|
312 | n/a | Py_ssize_t union_size, total_align; |
---|
313 | n/a | Py_ssize_t field_size = 0; |
---|
314 | n/a | int bitofs; |
---|
315 | n/a | PyObject *isPacked; |
---|
316 | n/a | int pack = 0; |
---|
317 | n/a | Py_ssize_t ffi_ofs; |
---|
318 | n/a | int big_endian; |
---|
319 | n/a | |
---|
320 | n/a | /* HACK Alert: I cannot be bothered to fix ctypes.com, so there has to |
---|
321 | n/a | be a way to use the old, broken sematics: _fields_ are not extended |
---|
322 | n/a | but replaced in subclasses. |
---|
323 | n/a | |
---|
324 | n/a | XXX Remove this in ctypes 1.0! |
---|
325 | n/a | */ |
---|
326 | n/a | int use_broken_old_ctypes_semantics; |
---|
327 | n/a | |
---|
328 | n/a | if (fields == NULL) |
---|
329 | n/a | return 0; |
---|
330 | n/a | |
---|
331 | n/a | #ifdef WORDS_BIGENDIAN |
---|
332 | n/a | big_endian = PyObject_HasAttrString(type, "_swappedbytes_") ? 0 : 1; |
---|
333 | n/a | #else |
---|
334 | n/a | big_endian = PyObject_HasAttrString(type, "_swappedbytes_") ? 1 : 0; |
---|
335 | n/a | #endif |
---|
336 | n/a | |
---|
337 | n/a | use_broken_old_ctypes_semantics = \ |
---|
338 | n/a | PyObject_HasAttrString(type, "_use_broken_old_ctypes_structure_semantics_"); |
---|
339 | n/a | |
---|
340 | n/a | isPacked = PyObject_GetAttrString(type, "_pack_"); |
---|
341 | n/a | if (isPacked) { |
---|
342 | n/a | pack = _PyLong_AsInt(isPacked); |
---|
343 | n/a | if (pack < 0 || PyErr_Occurred()) { |
---|
344 | n/a | Py_XDECREF(isPacked); |
---|
345 | n/a | PyErr_SetString(PyExc_ValueError, |
---|
346 | n/a | "_pack_ must be a non-negative integer"); |
---|
347 | n/a | return -1; |
---|
348 | n/a | } |
---|
349 | n/a | Py_DECREF(isPacked); |
---|
350 | n/a | } else |
---|
351 | n/a | PyErr_Clear(); |
---|
352 | n/a | |
---|
353 | n/a | len = PySequence_Length(fields); |
---|
354 | n/a | if (len == -1) { |
---|
355 | n/a | PyErr_SetString(PyExc_TypeError, |
---|
356 | n/a | "'_fields_' must be a sequence of pairs"); |
---|
357 | n/a | return -1; |
---|
358 | n/a | } |
---|
359 | n/a | |
---|
360 | n/a | stgdict = PyType_stgdict(type); |
---|
361 | n/a | if (!stgdict) |
---|
362 | n/a | return -1; |
---|
363 | n/a | /* If this structure/union is already marked final we cannot assign |
---|
364 | n/a | _fields_ anymore. */ |
---|
365 | n/a | |
---|
366 | n/a | if (stgdict->flags & DICTFLAG_FINAL) {/* is final ? */ |
---|
367 | n/a | PyErr_SetString(PyExc_AttributeError, |
---|
368 | n/a | "_fields_ is final"); |
---|
369 | n/a | return -1; |
---|
370 | n/a | } |
---|
371 | n/a | |
---|
372 | n/a | if (stgdict->format) { |
---|
373 | n/a | PyMem_Free(stgdict->format); |
---|
374 | n/a | stgdict->format = NULL; |
---|
375 | n/a | } |
---|
376 | n/a | |
---|
377 | n/a | if (stgdict->ffi_type_pointer.elements) |
---|
378 | n/a | PyMem_Free(stgdict->ffi_type_pointer.elements); |
---|
379 | n/a | |
---|
380 | n/a | basedict = PyType_stgdict((PyObject *)((PyTypeObject *)type)->tp_base); |
---|
381 | n/a | if (basedict && !use_broken_old_ctypes_semantics) { |
---|
382 | n/a | size = offset = basedict->size; |
---|
383 | n/a | align = basedict->align; |
---|
384 | n/a | union_size = 0; |
---|
385 | n/a | total_align = align ? align : 1; |
---|
386 | n/a | stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT; |
---|
387 | n/a | stgdict->ffi_type_pointer.elements = PyMem_New(ffi_type *, basedict->length + len + 1); |
---|
388 | n/a | if (stgdict->ffi_type_pointer.elements == NULL) { |
---|
389 | n/a | PyErr_NoMemory(); |
---|
390 | n/a | return -1; |
---|
391 | n/a | } |
---|
392 | n/a | memset(stgdict->ffi_type_pointer.elements, 0, |
---|
393 | n/a | sizeof(ffi_type *) * (basedict->length + len + 1)); |
---|
394 | n/a | if (basedict->length > 0) { |
---|
395 | n/a | memcpy(stgdict->ffi_type_pointer.elements, |
---|
396 | n/a | basedict->ffi_type_pointer.elements, |
---|
397 | n/a | sizeof(ffi_type *) * (basedict->length)); |
---|
398 | n/a | } |
---|
399 | n/a | ffi_ofs = basedict->length; |
---|
400 | n/a | } else { |
---|
401 | n/a | offset = 0; |
---|
402 | n/a | size = 0; |
---|
403 | n/a | align = 0; |
---|
404 | n/a | union_size = 0; |
---|
405 | n/a | total_align = 1; |
---|
406 | n/a | stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT; |
---|
407 | n/a | stgdict->ffi_type_pointer.elements = PyMem_New(ffi_type *, len + 1); |
---|
408 | n/a | if (stgdict->ffi_type_pointer.elements == NULL) { |
---|
409 | n/a | PyErr_NoMemory(); |
---|
410 | n/a | return -1; |
---|
411 | n/a | } |
---|
412 | n/a | memset(stgdict->ffi_type_pointer.elements, 0, |
---|
413 | n/a | sizeof(ffi_type *) * (len + 1)); |
---|
414 | n/a | ffi_ofs = 0; |
---|
415 | n/a | } |
---|
416 | n/a | |
---|
417 | n/a | assert(stgdict->format == NULL); |
---|
418 | n/a | if (isStruct && !isPacked) { |
---|
419 | n/a | stgdict->format = _ctypes_alloc_format_string(NULL, "T{"); |
---|
420 | n/a | } else { |
---|
421 | n/a | /* PEP3118 doesn't support union, or packed structures (well, |
---|
422 | n/a | only standard packing, but we dont support the pep for |
---|
423 | n/a | that). Use 'B' for bytes. */ |
---|
424 | n/a | stgdict->format = _ctypes_alloc_format_string(NULL, "B"); |
---|
425 | n/a | } |
---|
426 | n/a | if (stgdict->format == NULL) |
---|
427 | n/a | return -1; |
---|
428 | n/a | |
---|
429 | n/a | #define realdict ((PyObject *)&stgdict->dict) |
---|
430 | n/a | for (i = 0; i < len; ++i) { |
---|
431 | n/a | PyObject *name = NULL, *desc = NULL; |
---|
432 | n/a | PyObject *pair = PySequence_GetItem(fields, i); |
---|
433 | n/a | PyObject *prop; |
---|
434 | n/a | StgDictObject *dict; |
---|
435 | n/a | int bitsize = 0; |
---|
436 | n/a | |
---|
437 | n/a | if (!pair || !PyArg_ParseTuple(pair, "UO|i", &name, &desc, &bitsize)) { |
---|
438 | n/a | PyErr_SetString(PyExc_TypeError, |
---|
439 | n/a | "'_fields_' must be a sequence of (name, C type) pairs"); |
---|
440 | n/a | Py_XDECREF(pair); |
---|
441 | n/a | return -1; |
---|
442 | n/a | } |
---|
443 | n/a | dict = PyType_stgdict(desc); |
---|
444 | n/a | if (dict == NULL) { |
---|
445 | n/a | Py_DECREF(pair); |
---|
446 | n/a | PyErr_Format(PyExc_TypeError, |
---|
447 | n/a | "second item in _fields_ tuple (index %zd) must be a C type", |
---|
448 | n/a | i); |
---|
449 | n/a | return -1; |
---|
450 | n/a | } |
---|
451 | n/a | stgdict->ffi_type_pointer.elements[ffi_ofs + i] = &dict->ffi_type_pointer; |
---|
452 | n/a | if (dict->flags & (TYPEFLAG_ISPOINTER | TYPEFLAG_HASPOINTER)) |
---|
453 | n/a | stgdict->flags |= TYPEFLAG_HASPOINTER; |
---|
454 | n/a | dict->flags |= DICTFLAG_FINAL; /* mark field type final */ |
---|
455 | n/a | if (PyTuple_Size(pair) == 3) { /* bits specified */ |
---|
456 | n/a | switch(dict->ffi_type_pointer.type) { |
---|
457 | n/a | case FFI_TYPE_UINT8: |
---|
458 | n/a | case FFI_TYPE_UINT16: |
---|
459 | n/a | case FFI_TYPE_UINT32: |
---|
460 | n/a | case FFI_TYPE_SINT64: |
---|
461 | n/a | case FFI_TYPE_UINT64: |
---|
462 | n/a | break; |
---|
463 | n/a | |
---|
464 | n/a | case FFI_TYPE_SINT8: |
---|
465 | n/a | case FFI_TYPE_SINT16: |
---|
466 | n/a | case FFI_TYPE_SINT32: |
---|
467 | n/a | if (dict->getfunc != _ctypes_get_fielddesc("c")->getfunc |
---|
468 | n/a | #ifdef CTYPES_UNICODE |
---|
469 | n/a | && dict->getfunc != _ctypes_get_fielddesc("u")->getfunc |
---|
470 | n/a | #endif |
---|
471 | n/a | ) |
---|
472 | n/a | break; |
---|
473 | n/a | /* else fall through */ |
---|
474 | n/a | default: |
---|
475 | n/a | PyErr_Format(PyExc_TypeError, |
---|
476 | n/a | "bit fields not allowed for type %s", |
---|
477 | n/a | ((PyTypeObject *)desc)->tp_name); |
---|
478 | n/a | Py_DECREF(pair); |
---|
479 | n/a | return -1; |
---|
480 | n/a | } |
---|
481 | n/a | if (bitsize <= 0 || bitsize > dict->size * 8) { |
---|
482 | n/a | PyErr_SetString(PyExc_ValueError, |
---|
483 | n/a | "number of bits invalid for bit field"); |
---|
484 | n/a | Py_DECREF(pair); |
---|
485 | n/a | return -1; |
---|
486 | n/a | } |
---|
487 | n/a | } else |
---|
488 | n/a | bitsize = 0; |
---|
489 | n/a | |
---|
490 | n/a | if (isStruct && !isPacked) { |
---|
491 | n/a | const char *fieldfmt = dict->format ? dict->format : "B"; |
---|
492 | n/a | const char *fieldname = PyUnicode_AsUTF8(name); |
---|
493 | n/a | char *ptr; |
---|
494 | n/a | Py_ssize_t len; |
---|
495 | n/a | char *buf; |
---|
496 | n/a | |
---|
497 | n/a | if (fieldname == NULL) |
---|
498 | n/a | { |
---|
499 | n/a | Py_DECREF(pair); |
---|
500 | n/a | return -1; |
---|
501 | n/a | } |
---|
502 | n/a | |
---|
503 | n/a | len = strlen(fieldname) + strlen(fieldfmt); |
---|
504 | n/a | |
---|
505 | n/a | buf = PyMem_Malloc(len + 2 + 1); |
---|
506 | n/a | if (buf == NULL) { |
---|
507 | n/a | Py_DECREF(pair); |
---|
508 | n/a | PyErr_NoMemory(); |
---|
509 | n/a | return -1; |
---|
510 | n/a | } |
---|
511 | n/a | sprintf(buf, "%s:%s:", fieldfmt, fieldname); |
---|
512 | n/a | |
---|
513 | n/a | ptr = stgdict->format; |
---|
514 | n/a | if (dict->shape != NULL) { |
---|
515 | n/a | stgdict->format = _ctypes_alloc_format_string_with_shape( |
---|
516 | n/a | dict->ndim, dict->shape, stgdict->format, buf); |
---|
517 | n/a | } else { |
---|
518 | n/a | stgdict->format = _ctypes_alloc_format_string(stgdict->format, buf); |
---|
519 | n/a | } |
---|
520 | n/a | PyMem_Free(ptr); |
---|
521 | n/a | PyMem_Free(buf); |
---|
522 | n/a | |
---|
523 | n/a | if (stgdict->format == NULL) { |
---|
524 | n/a | Py_DECREF(pair); |
---|
525 | n/a | return -1; |
---|
526 | n/a | } |
---|
527 | n/a | } |
---|
528 | n/a | |
---|
529 | n/a | if (isStruct) { |
---|
530 | n/a | prop = PyCField_FromDesc(desc, i, |
---|
531 | n/a | &field_size, bitsize, &bitofs, |
---|
532 | n/a | &size, &offset, &align, |
---|
533 | n/a | pack, big_endian); |
---|
534 | n/a | } else /* union */ { |
---|
535 | n/a | size = 0; |
---|
536 | n/a | offset = 0; |
---|
537 | n/a | align = 0; |
---|
538 | n/a | prop = PyCField_FromDesc(desc, i, |
---|
539 | n/a | &field_size, bitsize, &bitofs, |
---|
540 | n/a | &size, &offset, &align, |
---|
541 | n/a | pack, big_endian); |
---|
542 | n/a | union_size = max(size, union_size); |
---|
543 | n/a | } |
---|
544 | n/a | total_align = max(align, total_align); |
---|
545 | n/a | |
---|
546 | n/a | if (!prop) { |
---|
547 | n/a | Py_DECREF(pair); |
---|
548 | n/a | return -1; |
---|
549 | n/a | } |
---|
550 | n/a | if (-1 == PyObject_SetAttr(type, name, prop)) { |
---|
551 | n/a | Py_DECREF(prop); |
---|
552 | n/a | Py_DECREF(pair); |
---|
553 | n/a | return -1; |
---|
554 | n/a | } |
---|
555 | n/a | Py_DECREF(pair); |
---|
556 | n/a | Py_DECREF(prop); |
---|
557 | n/a | } |
---|
558 | n/a | #undef realdict |
---|
559 | n/a | |
---|
560 | n/a | if (isStruct && !isPacked) { |
---|
561 | n/a | char *ptr = stgdict->format; |
---|
562 | n/a | stgdict->format = _ctypes_alloc_format_string(stgdict->format, "}"); |
---|
563 | n/a | PyMem_Free(ptr); |
---|
564 | n/a | if (stgdict->format == NULL) |
---|
565 | n/a | return -1; |
---|
566 | n/a | } |
---|
567 | n/a | |
---|
568 | n/a | if (!isStruct) |
---|
569 | n/a | size = union_size; |
---|
570 | n/a | |
---|
571 | n/a | /* Adjust the size according to the alignment requirements */ |
---|
572 | n/a | size = ((size + total_align - 1) / total_align) * total_align; |
---|
573 | n/a | |
---|
574 | n/a | stgdict->ffi_type_pointer.alignment = Py_SAFE_DOWNCAST(total_align, |
---|
575 | n/a | Py_ssize_t, |
---|
576 | n/a | unsigned short); |
---|
577 | n/a | stgdict->ffi_type_pointer.size = size; |
---|
578 | n/a | |
---|
579 | n/a | stgdict->size = size; |
---|
580 | n/a | stgdict->align = total_align; |
---|
581 | n/a | stgdict->length = len; /* ADD ffi_ofs? */ |
---|
582 | n/a | |
---|
583 | n/a | /* We did check that this flag was NOT set above, it must not |
---|
584 | n/a | have been set until now. */ |
---|
585 | n/a | if (stgdict->flags & DICTFLAG_FINAL) { |
---|
586 | n/a | PyErr_SetString(PyExc_AttributeError, |
---|
587 | n/a | "Structure or union cannot contain itself"); |
---|
588 | n/a | return -1; |
---|
589 | n/a | } |
---|
590 | n/a | stgdict->flags |= DICTFLAG_FINAL; |
---|
591 | n/a | |
---|
592 | n/a | return MakeAnonFields(type); |
---|
593 | n/a | } |
---|