1 /*****************************************************************
2 This file should be kept compatible with Python 2.3, see PEP 291.
3 *****************************************************************/
13 /******************************************************************/
15 StdDict - a dictionary subclass, containing additional C accessible fields
20 /* Seems we need this, otherwise we get problems when calling
21 * PyDict_SetItem() (ma_lookup is NULL)
24 PyCStgDict_init(StgDictObject
*self
, PyObject
*args
, PyObject
*kwds
)
26 if (PyDict_Type
.tp_init((PyObject
*)self
, args
, kwds
) < 0)
35 PyCStgDict_clear(StgDictObject
*self
)
37 Py_CLEAR(self
->proto
);
38 Py_CLEAR(self
->argtypes
);
39 Py_CLEAR(self
->converters
);
40 Py_CLEAR(self
->restype
);
41 Py_CLEAR(self
->checker
);
46 PyCStgDict_dealloc(StgDictObject
*self
)
48 PyCStgDict_clear(self
);
49 PyMem_Free(self
->format
);
50 PyMem_Free(self
->shape
);
51 PyMem_Free(self
->ffi_type_pointer
.elements
);
52 PyDict_Type
.tp_dealloc((PyObject
*)self
);
56 PyCStgDict_clone(StgDictObject
*dst
, StgDictObject
*src
)
61 PyCStgDict_clear(dst
);
62 PyMem_Free(dst
->ffi_type_pointer
.elements
);
63 PyMem_Free(dst
->format
);
65 PyMem_Free(dst
->shape
);
67 dst
->ffi_type_pointer
.elements
= NULL
;
71 memcpy(d
+ sizeof(PyDictObject
),
72 s
+ sizeof(PyDictObject
),
73 sizeof(StgDictObject
) - sizeof(PyDictObject
));
75 Py_XINCREF(dst
->proto
);
76 Py_XINCREF(dst
->argtypes
);
77 Py_XINCREF(dst
->converters
);
78 Py_XINCREF(dst
->restype
);
79 Py_XINCREF(dst
->checker
);
82 dst
->format
= PyMem_Malloc(strlen(src
->format
) + 1);
83 if (dst
->format
== NULL
)
85 strcpy(dst
->format
, src
->format
);
88 dst
->shape
= PyMem_Malloc(sizeof(Py_ssize_t
) * src
->ndim
);
89 if (dst
->shape
== NULL
)
91 memcpy(dst
->shape
, src
->shape
,
92 sizeof(Py_ssize_t
) * src
->ndim
);
95 if (src
->ffi_type_pointer
.elements
== NULL
)
97 size
= sizeof(ffi_type
*) * (src
->length
+ 1);
98 dst
->ffi_type_pointer
.elements
= PyMem_Malloc(size
);
99 if (dst
->ffi_type_pointer
.elements
== NULL
) {
103 memcpy(dst
->ffi_type_pointer
.elements
,
104 src
->ffi_type_pointer
.elements
,
109 PyTypeObject PyCStgDict_Type
= {
110 PyVarObject_HEAD_INIT(NULL
, 0)
112 sizeof(StgDictObject
),
114 (destructor
)PyCStgDict_dealloc
, /* tp_dealloc */
120 0, /* tp_as_number */
121 0, /* tp_as_sequence */
122 0, /* tp_as_mapping */
128 0, /* tp_as_buffer */
129 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
, /* tp_flags */
133 0, /* tp_richcompare */
134 0, /* tp_weaklistoffset */
142 0, /* tp_descr_get */
143 0, /* tp_descr_set */
144 0, /* tp_dictoffset */
145 (initproc
)PyCStgDict_init
, /* tp_init */
151 /* May return NULL, but does not set an exception! */
153 PyType_stgdict(PyObject
*obj
)
157 if (!PyType_Check(obj
))
159 type
= (PyTypeObject
*)obj
;
160 if (!PyType_HasFeature(type
, Py_TPFLAGS_HAVE_CLASS
))
162 if (!type
->tp_dict
|| !PyCStgDict_CheckExact(type
->tp_dict
))
164 return (StgDictObject
*)type
->tp_dict
;
167 /* May return NULL, but does not set an exception! */
169 This function should be as fast as possible, so we don't call PyType_stgdict
170 above but inline the code, and avoid the PyType_Check().
173 PyObject_stgdict(PyObject
*self
)
175 PyTypeObject
*type
= self
->ob_type
;
176 if (!PyType_HasFeature(type
, Py_TPFLAGS_HAVE_CLASS
))
178 if (!type
->tp_dict
|| !PyCStgDict_CheckExact(type
->tp_dict
))
180 return (StgDictObject
*)type
->tp_dict
;
183 /* descr is the descriptor for a field marked as anonymous. Get all the
184 _fields_ descriptors from descr->proto, create new descriptors with offset
185 and index adjusted, and stuff them into type.
188 MakeFields(PyObject
*type
, CFieldObject
*descr
,
189 Py_ssize_t index
, Py_ssize_t offset
)
195 fields
= PyObject_GetAttrString(descr
->proto
, "_fields_");
198 fieldlist
= PySequence_Fast(fields
, "_fields_ must be a sequence");
200 if (fieldlist
== NULL
)
203 for (i
= 0; i
< PySequence_Fast_GET_SIZE(fieldlist
); ++i
) {
204 PyObject
*pair
= PySequence_Fast_GET_ITEM(fieldlist
, i
); /* borrowed */
205 PyObject
*fname
, *ftype
, *bits
;
206 CFieldObject
*fdescr
;
207 CFieldObject
*new_descr
;
208 /* Convert to PyArg_UnpackTuple... */
209 if (!PyArg_ParseTuple(pair
, "OO|O", &fname
, &ftype
, &bits
)) {
210 Py_DECREF(fieldlist
);
213 fdescr
= (CFieldObject
*)PyObject_GetAttr(descr
->proto
, fname
);
214 if (fdescr
== NULL
) {
215 Py_DECREF(fieldlist
);
218 if (Py_TYPE(fdescr
) != &PyCField_Type
) {
219 PyErr_SetString(PyExc_TypeError
, "unexpected type");
221 Py_DECREF(fieldlist
);
224 if (fdescr
->anonymous
) {
225 int rc
= MakeFields(type
, fdescr
,
226 index
+ fdescr
->index
,
227 offset
+ fdescr
->offset
);
230 Py_DECREF(fieldlist
);
235 new_descr
= (CFieldObject
*)PyObject_CallObject((PyObject
*)&PyCField_Type
, NULL
);
236 if (new_descr
== NULL
) {
238 Py_DECREF(fieldlist
);
241 assert(Py_TYPE(new_descr
) == &PyCField_Type
);
242 new_descr
->size
= fdescr
->size
;
243 new_descr
->offset
= fdescr
->offset
+ offset
;
244 new_descr
->index
= fdescr
->index
+ index
;
245 new_descr
->proto
= fdescr
->proto
;
246 Py_XINCREF(new_descr
->proto
);
247 new_descr
->getfunc
= fdescr
->getfunc
;
248 new_descr
->setfunc
= fdescr
->setfunc
;
252 if (-1 == PyObject_SetAttr(type
, fname
, (PyObject
*)new_descr
)) {
253 Py_DECREF(fieldlist
);
254 Py_DECREF(new_descr
);
257 Py_DECREF(new_descr
);
259 Py_DECREF(fieldlist
);
263 /* Iterate over the names in the type's _anonymous_ attribute, if present,
266 MakeAnonFields(PyObject
*type
)
269 PyObject
*anon_names
;
272 anon
= PyObject_GetAttrString(type
, "_anonymous_");
277 anon_names
= PySequence_Fast(anon
, "_anonymous_ must be a sequence");
279 if (anon_names
== NULL
)
282 for (i
= 0; i
< PySequence_Fast_GET_SIZE(anon_names
); ++i
) {
283 PyObject
*fname
= PySequence_Fast_GET_ITEM(anon_names
, i
); /* borrowed */
284 CFieldObject
*descr
= (CFieldObject
*)PyObject_GetAttr(type
, fname
);
286 Py_DECREF(anon_names
);
289 assert(Py_TYPE(descr
) == &PyCField_Type
);
290 descr
->anonymous
= 1;
292 /* descr is in the field descriptor. */
293 if (-1 == MakeFields(type
, (CFieldObject
*)descr
,
294 ((CFieldObject
*)descr
)->index
,
295 ((CFieldObject
*)descr
)->offset
)) {
297 Py_DECREF(anon_names
);
303 Py_DECREF(anon_names
);
308 Retrive the (optional) _pack_ attribute from a type, the _fields_ attribute,
309 and create an StgDictObject. Used for Structure and Union subclasses.
312 PyCStructUnionType_update_stgdict(PyObject
*type
, PyObject
*fields
, int isStruct
)
314 StgDictObject
*stgdict
, *basedict
;
315 Py_ssize_t len
, offset
, size
, align
, i
;
316 Py_ssize_t union_size
, total_align
;
317 Py_ssize_t field_size
= 0;
324 /* HACK Alert: I cannot be bothered to fix ctypes.com, so there has to
325 be a way to use the old, broken sematics: _fields_ are not extended
326 but replaced in subclasses.
328 XXX Remove this in ctypes 1.0!
330 int use_broken_old_ctypes_semantics
;
335 #ifdef WORDS_BIGENDIAN
336 big_endian
= PyObject_HasAttrString(type
, "_swappedbytes_") ? 0 : 1;
338 big_endian
= PyObject_HasAttrString(type
, "_swappedbytes_") ? 1 : 0;
341 use_broken_old_ctypes_semantics
= \
342 PyObject_HasAttrString(type
, "_use_broken_old_ctypes_structure_semantics_");
344 isPacked
= PyObject_GetAttrString(type
, "_pack_");
346 pack
= PyInt_AsLong(isPacked
);
347 if (pack
< 0 || PyErr_Occurred()) {
348 Py_XDECREF(isPacked
);
349 PyErr_SetString(PyExc_ValueError
,
350 "_pack_ must be a non-negative integer");
357 len
= PySequence_Length(fields
);
359 PyErr_SetString(PyExc_TypeError
,
360 "'_fields_' must be a sequence of pairs");
364 stgdict
= PyType_stgdict(type
);
367 /* If this structure/union is already marked final we cannot assign
370 if (stgdict
->flags
& DICTFLAG_FINAL
) {/* is final ? */
371 PyErr_SetString(PyExc_AttributeError
,
372 "_fields_ is final");
376 if (stgdict
->format
) {
377 PyMem_Free(stgdict
->format
);
378 stgdict
->format
= NULL
;
381 if (stgdict
->ffi_type_pointer
.elements
)
382 PyMem_Free(stgdict
->ffi_type_pointer
.elements
);
384 basedict
= PyType_stgdict((PyObject
*)((PyTypeObject
*)type
)->tp_base
);
385 if (basedict
&& !use_broken_old_ctypes_semantics
) {
386 size
= offset
= basedict
->size
;
387 align
= basedict
->align
;
389 total_align
= align
? align
: 1;
390 stgdict
->ffi_type_pointer
.type
= FFI_TYPE_STRUCT
;
391 stgdict
->ffi_type_pointer
.elements
= PyMem_Malloc(sizeof(ffi_type
*) * (basedict
->length
+ len
+ 1));
392 if (stgdict
->ffi_type_pointer
.elements
== NULL
) {
396 memset(stgdict
->ffi_type_pointer
.elements
, 0,
397 sizeof(ffi_type
*) * (basedict
->length
+ len
+ 1));
398 memcpy(stgdict
->ffi_type_pointer
.elements
,
399 basedict
->ffi_type_pointer
.elements
,
400 sizeof(ffi_type
*) * (basedict
->length
));
401 ffi_ofs
= basedict
->length
;
408 stgdict
->ffi_type_pointer
.type
= FFI_TYPE_STRUCT
;
409 stgdict
->ffi_type_pointer
.elements
= PyMem_Malloc(sizeof(ffi_type
*) * (len
+ 1));
410 if (stgdict
->ffi_type_pointer
.elements
== NULL
) {
414 memset(stgdict
->ffi_type_pointer
.elements
, 0,
415 sizeof(ffi_type
*) * (len
+ 1));
419 assert(stgdict
->format
== NULL
);
420 if (isStruct
&& !isPacked
) {
421 stgdict
->format
= _ctypes_alloc_format_string(NULL
, "T{");
423 /* PEP3118 doesn't support union, or packed structures (well,
424 only standard packing, but we dont support the pep for
425 that). Use 'B' for bytes. */
426 stgdict
->format
= _ctypes_alloc_format_string(NULL
, "B");
429 #define realdict ((PyObject *)&stgdict->dict)
430 for (i
= 0; i
< len
; ++i
) {
431 PyObject
*name
= NULL
, *desc
= NULL
;
432 PyObject
*pair
= PySequence_GetItem(fields
, i
);
437 if (!pair
|| !PyArg_ParseTuple(pair
, "OO|i", &name
, &desc
, &bitsize
)) {
438 PyErr_SetString(PyExc_AttributeError
,
439 "'_fields_' must be a sequence of pairs");
443 dict
= PyType_stgdict(desc
);
446 PyErr_Format(PyExc_TypeError
,
447 #if (PY_VERSION_HEX < 0x02050000)
448 "second item in _fields_ tuple (index %d) must be a C type",
450 "second item in _fields_ tuple (index %zd) must be a C type",
455 stgdict
->ffi_type_pointer
.elements
[ffi_ofs
+ i
] = &dict
->ffi_type_pointer
;
456 if (dict
->flags
& (TYPEFLAG_ISPOINTER
| TYPEFLAG_HASPOINTER
))
457 stgdict
->flags
|= TYPEFLAG_HASPOINTER
;
458 dict
->flags
|= DICTFLAG_FINAL
; /* mark field type final */
459 if (PyTuple_Size(pair
) == 3) { /* bits specified */
460 switch(dict
->ffi_type_pointer
.type
) {
462 case FFI_TYPE_UINT16
:
463 case FFI_TYPE_UINT32
:
464 case FFI_TYPE_SINT64
:
465 case FFI_TYPE_UINT64
:
469 case FFI_TYPE_SINT16
:
470 case FFI_TYPE_SINT32
:
471 if (dict
->getfunc
!= _ctypes_get_fielddesc("c")->getfunc
472 #ifdef CTYPES_UNICODE
473 && dict
->getfunc
!= _ctypes_get_fielddesc("u")->getfunc
477 /* else fall through */
479 PyErr_Format(PyExc_TypeError
,
480 "bit fields not allowed for type %s",
481 ((PyTypeObject
*)desc
)->tp_name
);
485 if (bitsize
<= 0 || bitsize
> dict
->size
* 8) {
486 PyErr_SetString(PyExc_ValueError
,
487 "number of bits invalid for bit field");
493 if (isStruct
&& !isPacked
) {
494 char *fieldfmt
= dict
->format
? dict
->format
: "B";
495 char *fieldname
= PyString_AsString(name
);
497 Py_ssize_t len
= strlen(fieldname
) + strlen(fieldfmt
);
498 char *buf
= alloca(len
+ 2 + 1);
500 sprintf(buf
, "%s:%s:", fieldfmt
, fieldname
);
502 ptr
= stgdict
->format
;
503 stgdict
->format
= _ctypes_alloc_format_string(stgdict
->format
, buf
);
506 if (stgdict
->format
== NULL
) {
512 prop
= PyCField_FromDesc(desc
, i
,
513 &field_size
, bitsize
, &bitofs
,
514 &size
, &offset
, &align
,
520 prop
= PyCField_FromDesc(desc
, i
,
521 &field_size
, bitsize
, &bitofs
,
522 &size
, &offset
, &align
,
524 union_size
= max(size
, union_size
);
526 total_align
= max(align
, total_align
);
532 if (-1 == PyObject_SetAttr(type
, name
, prop
)) {
542 if (isStruct
&& !isPacked
) {
543 char *ptr
= stgdict
->format
;
544 stgdict
->format
= _ctypes_alloc_format_string(stgdict
->format
, "}");
546 if (stgdict
->format
== NULL
)
553 /* Adjust the size according to the alignment requirements */
554 size
= ((size
+ total_align
- 1) / total_align
) * total_align
;
556 stgdict
->ffi_type_pointer
.alignment
= Py_SAFE_DOWNCAST(total_align
,
559 stgdict
->ffi_type_pointer
.size
= size
;
561 stgdict
->size
= size
;
562 stgdict
->align
= total_align
;
563 stgdict
->length
= len
; /* ADD ffi_ofs? */
565 /* We did check that this flag was NOT set above, it must not
566 have been set until now. */
567 if (stgdict
->flags
& DICTFLAG_FINAL
) {
568 PyErr_SetString(PyExc_AttributeError
,
569 "Structure or union cannot contain itself");
572 stgdict
->flags
|= DICTFLAG_FINAL
;
574 return MakeAnonFields(type
);