stgdict.c revision cf316a171e562a7bb7490749818ddb3174a295b1
1/***************************************************************** 2 This file should be kept compatible with Python 2.3, see PEP 291. 3 *****************************************************************/ 4 5#include "Python.h" 6#include <ffi.h> 7#ifdef MS_WIN32 8#include <windows.h> 9#include <malloc.h> 10#endif 11#include "ctypes.h" 12 13/******************************************************************/ 14/* 15 StdDict - a dictionary subclass, containing additional C accessible fields 16 17 XXX blabla more 18*/ 19 20/* Seems we need this, otherwise we get problems when calling 21 * PyDict_SetItem() (ma_lookup is NULL) 22 */ 23static int 24PyCStgDict_init(StgDictObject *self, PyObject *args, PyObject *kwds) 25{ 26 if (PyDict_Type.tp_init((PyObject *)self, args, kwds) < 0) 27 return -1; 28 self->format = NULL; 29 self->ndim = 0; 30 self->shape = NULL; 31 return 0; 32} 33 34static int 35PyCStgDict_clear(StgDictObject *self) 36{ 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); 42 return 0; 43} 44 45static void 46PyCStgDict_dealloc(StgDictObject *self) 47{ 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); 53} 54 55int 56PyCStgDict_clone(StgDictObject *dst, StgDictObject *src) 57{ 58 char *d, *s; 59 Py_ssize_t size; 60 61 PyCStgDict_clear(dst); 62 PyMem_Free(dst->ffi_type_pointer.elements); 63 PyMem_Free(dst->format); 64 dst->format = NULL; 65 PyMem_Free(dst->shape); 66 dst->shape = NULL; 67 dst->ffi_type_pointer.elements = NULL; 68 69 d = (char *)dst; 70 s = (char *)src; 71 memcpy(d + sizeof(PyDictObject), 72 s + sizeof(PyDictObject), 73 sizeof(StgDictObject) - sizeof(PyDictObject)); 74 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); 80 81 if (src->format) { 82 dst->format = PyMem_Malloc(strlen(src->format) + 1); 83 if (dst->format == NULL) 84 return -1; 85 strcpy(dst->format, src->format); 86 } 87 if (src->shape) { 88 dst->shape = PyMem_Malloc(sizeof(Py_ssize_t) * src->ndim); 89 if (dst->shape == NULL) 90 return -1; 91 memcpy(dst->shape, src->shape, 92 sizeof(Py_ssize_t) * src->ndim); 93 } 94 95 if (src->ffi_type_pointer.elements == NULL) 96 return 0; 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) { 100 PyErr_NoMemory(); 101 return -1; 102 } 103 memcpy(dst->ffi_type_pointer.elements, 104 src->ffi_type_pointer.elements, 105 size); 106 return 0; 107} 108 109PyTypeObject PyCStgDict_Type = { 110 PyVarObject_HEAD_INIT(NULL, 0) 111 "StgDict", 112 sizeof(StgDictObject), 113 0, 114 (destructor)PyCStgDict_dealloc, /* tp_dealloc */ 115 0, /* tp_print */ 116 0, /* tp_getattr */ 117 0, /* tp_setattr */ 118 0, /* tp_compare */ 119 0, /* tp_repr */ 120 0, /* tp_as_number */ 121 0, /* tp_as_sequence */ 122 0, /* tp_as_mapping */ 123 0, /* tp_hash */ 124 0, /* tp_call */ 125 0, /* tp_str */ 126 0, /* tp_getattro */ 127 0, /* tp_setattro */ 128 0, /* tp_as_buffer */ 129 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ 130 0, /* tp_doc */ 131 0, /* tp_traverse */ 132 0, /* tp_clear */ 133 0, /* tp_richcompare */ 134 0, /* tp_weaklistoffset */ 135 0, /* tp_iter */ 136 0, /* tp_iternext */ 137 0, /* tp_methods */ 138 0, /* tp_members */ 139 0, /* tp_getset */ 140 0, /* tp_base */ 141 0, /* tp_dict */ 142 0, /* tp_descr_get */ 143 0, /* tp_descr_set */ 144 0, /* tp_dictoffset */ 145 (initproc)PyCStgDict_init, /* tp_init */ 146 0, /* tp_alloc */ 147 0, /* tp_new */ 148 0, /* tp_free */ 149}; 150 151/* May return NULL, but does not set an exception! */ 152StgDictObject * 153PyType_stgdict(PyObject *obj) 154{ 155 PyTypeObject *type; 156 157 if (!PyType_Check(obj)) 158 return NULL; 159 type = (PyTypeObject *)obj; 160 if (!PyType_HasFeature(type, Py_TPFLAGS_HAVE_CLASS)) 161 return NULL; 162 if (!type->tp_dict || !PyCStgDict_CheckExact(type->tp_dict)) 163 return NULL; 164 return (StgDictObject *)type->tp_dict; 165} 166 167/* May return NULL, but does not set an exception! */ 168/* 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(). 171*/ 172StgDictObject * 173PyObject_stgdict(PyObject *self) 174{ 175 PyTypeObject *type = self->ob_type; 176 if (!PyType_HasFeature(type, Py_TPFLAGS_HAVE_CLASS)) 177 return NULL; 178 if (!type->tp_dict || !PyCStgDict_CheckExact(type->tp_dict)) 179 return NULL; 180 return (StgDictObject *)type->tp_dict; 181} 182 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. 186 */ 187static int 188MakeFields(PyObject *type, CFieldObject *descr, 189 Py_ssize_t index, Py_ssize_t offset) 190{ 191 Py_ssize_t i; 192 PyObject *fields; 193 PyObject *fieldlist; 194 195 fields = PyObject_GetAttrString(descr->proto, "_fields_"); 196 if (fields == NULL) 197 return -1; 198 fieldlist = PySequence_Fast(fields, "_fields_ must be a sequence"); 199 Py_DECREF(fields); 200 if (fieldlist == NULL) 201 return -1; 202 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); 211 return -1; 212 } 213 fdescr = (CFieldObject *)PyObject_GetAttr(descr->proto, fname); 214 if (fdescr == NULL) { 215 Py_DECREF(fieldlist); 216 return -1; 217 } 218 if (Py_TYPE(fdescr) != &PyCField_Type) { 219 PyErr_SetString(PyExc_TypeError, "unexpected type"); 220 Py_DECREF(fdescr); 221 Py_DECREF(fieldlist); 222 return -1; 223 } 224 if (fdescr->anonymous) { 225 int rc = MakeFields(type, fdescr, 226 index + fdescr->index, 227 offset + fdescr->offset); 228 Py_DECREF(fdescr); 229 if (rc == -1) { 230 Py_DECREF(fieldlist); 231 return -1; 232 } 233 continue; 234 } 235 new_descr = (CFieldObject *)PyObject_CallObject((PyObject *)&PyCField_Type, NULL); 236 if (new_descr == NULL) { 237 Py_DECREF(fdescr); 238 Py_DECREF(fieldlist); 239 return -1; 240 } 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; 249 250 Py_DECREF(fdescr); 251 252 if (-1 == PyObject_SetAttr(type, fname, (PyObject *)new_descr)) { 253 Py_DECREF(fieldlist); 254 Py_DECREF(new_descr); 255 return -1; 256 } 257 Py_DECREF(new_descr); 258 } 259 Py_DECREF(fieldlist); 260 return 0; 261} 262 263/* Iterate over the names in the type's _anonymous_ attribute, if present, 264 */ 265static int 266MakeAnonFields(PyObject *type) 267{ 268 PyObject *anon; 269 PyObject *anon_names; 270 Py_ssize_t i; 271 272 anon = PyObject_GetAttrString(type, "_anonymous_"); 273 if (anon == NULL) { 274 PyErr_Clear(); 275 return 0; 276 } 277 anon_names = PySequence_Fast(anon, "_anonymous_ must be a sequence"); 278 Py_DECREF(anon); 279 if (anon_names == NULL) 280 return -1; 281 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); 285 if (descr == NULL) { 286 Py_DECREF(anon_names); 287 return -1; 288 } 289 assert(Py_TYPE(descr) == &PyCField_Type); 290 descr->anonymous = 1; 291 292 /* descr is in the field descriptor. */ 293 if (-1 == MakeFields(type, (CFieldObject *)descr, 294 ((CFieldObject *)descr)->index, 295 ((CFieldObject *)descr)->offset)) { 296 Py_DECREF(descr); 297 Py_DECREF(anon_names); 298 return -1; 299 } 300 Py_DECREF(descr); 301 } 302 303 Py_DECREF(anon_names); 304 return 0; 305} 306 307/* 308 Retrive the (optional) _pack_ attribute from a type, the _fields_ attribute, 309 and create an StgDictObject. Used for Structure and Union subclasses. 310*/ 311int 312PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct) 313{ 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; 318 int bitofs; 319 PyObject *isPacked; 320 int pack = 0; 321 Py_ssize_t ffi_ofs; 322 int big_endian; 323 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. 327 328 XXX Remove this in ctypes 1.0! 329 */ 330 int use_broken_old_ctypes_semantics; 331 332 if (fields == NULL) 333 return 0; 334 335#ifdef WORDS_BIGENDIAN 336 big_endian = PyObject_HasAttrString(type, "_swappedbytes_") ? 0 : 1; 337#else 338 big_endian = PyObject_HasAttrString(type, "_swappedbytes_") ? 1 : 0; 339#endif 340 341 use_broken_old_ctypes_semantics = \ 342 PyObject_HasAttrString(type, "_use_broken_old_ctypes_structure_semantics_"); 343 344 isPacked = PyObject_GetAttrString(type, "_pack_"); 345 if (isPacked) { 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"); 351 return -1; 352 } 353 Py_DECREF(isPacked); 354 } else 355 PyErr_Clear(); 356 357 len = PySequence_Length(fields); 358 if (len == -1) { 359 PyErr_SetString(PyExc_TypeError, 360 "'_fields_' must be a sequence of pairs"); 361 return -1; 362 } 363 364 stgdict = PyType_stgdict(type); 365 if (!stgdict) 366 return -1; 367 /* If this structure/union is already marked final we cannot assign 368 _fields_ anymore. */ 369 370 if (stgdict->flags & DICTFLAG_FINAL) {/* is final ? */ 371 PyErr_SetString(PyExc_AttributeError, 372 "_fields_ is final"); 373 return -1; 374 } 375 376 if (stgdict->format) { 377 PyMem_Free(stgdict->format); 378 stgdict->format = NULL; 379 } 380 381 if (stgdict->ffi_type_pointer.elements) 382 PyMem_Free(stgdict->ffi_type_pointer.elements); 383 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; 388 union_size = 0; 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) { 393 PyErr_NoMemory(); 394 return -1; 395 } 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; 402 } else { 403 offset = 0; 404 size = 0; 405 align = 0; 406 union_size = 0; 407 total_align = 1; 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) { 411 PyErr_NoMemory(); 412 return -1; 413 } 414 memset(stgdict->ffi_type_pointer.elements, 0, 415 sizeof(ffi_type *) * (len + 1)); 416 ffi_ofs = 0; 417 } 418 419 assert(stgdict->format == NULL); 420 if (isStruct && !isPacked) { 421 stgdict->format = _ctypes_alloc_format_string(NULL, "T{"); 422 } else { 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"); 427 } 428 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); 433 PyObject *prop; 434 StgDictObject *dict; 435 int bitsize = 0; 436 437 if (!pair || !PyArg_ParseTuple(pair, "OO|i", &name, &desc, &bitsize)) { 438 PyErr_SetString(PyExc_AttributeError, 439 "'_fields_' must be a sequence of pairs"); 440 Py_XDECREF(pair); 441 return -1; 442 } 443 dict = PyType_stgdict(desc); 444 if (dict == NULL) { 445 Py_DECREF(pair); 446 PyErr_Format(PyExc_TypeError, 447#if (PY_VERSION_HEX < 0x02050000) 448 "second item in _fields_ tuple (index %d) must be a C type", 449#else 450 "second item in _fields_ tuple (index %zd) must be a C type", 451#endif 452 i); 453 return -1; 454 } 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) { 461 case FFI_TYPE_UINT8: 462 case FFI_TYPE_UINT16: 463 case FFI_TYPE_UINT32: 464 case FFI_TYPE_SINT64: 465 case FFI_TYPE_UINT64: 466 break; 467 468 case FFI_TYPE_SINT8: 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 474#endif 475 ) 476 break; 477 /* else fall through */ 478 default: 479 PyErr_Format(PyExc_TypeError, 480 "bit fields not allowed for type %s", 481 ((PyTypeObject *)desc)->tp_name); 482 Py_DECREF(pair); 483 return -1; 484 } 485 if (bitsize <= 0 || bitsize > dict->size * 8) { 486 PyErr_SetString(PyExc_ValueError, 487 "number of bits invalid for bit field"); 488 Py_DECREF(pair); 489 return -1; 490 } 491 } else 492 bitsize = 0; 493 if (isStruct && !isPacked) { 494 char *fieldfmt = dict->format ? dict->format : "B"; 495 char *fieldname = PyString_AsString(name); 496 char *ptr; 497 Py_ssize_t len; 498 char *buf; 499 500 if (fieldname == NULL) 501 { 502 PyErr_Format(PyExc_TypeError, 503 "structure field name must be string not %s", 504 name->ob_type->tp_name); 505 506 Py_DECREF(pair); 507 return -1; 508 } 509 510 len = strlen(fieldname) + strlen(fieldfmt); 511 buf = alloca(len + 2 + 1); 512 513 sprintf(buf, "%s:%s:", fieldfmt, fieldname); 514 515 ptr = stgdict->format; 516 stgdict->format = _ctypes_alloc_format_string(stgdict->format, buf); 517 PyMem_Free(ptr); 518 519 if (stgdict->format == NULL) { 520 Py_DECREF(pair); 521 return -1; 522 } 523 } 524 if (isStruct) { 525 prop = PyCField_FromDesc(desc, i, 526 &field_size, bitsize, &bitofs, 527 &size, &offset, &align, 528 pack, big_endian); 529 } else /* union */ { 530 size = 0; 531 offset = 0; 532 align = 0; 533 prop = PyCField_FromDesc(desc, i, 534 &field_size, bitsize, &bitofs, 535 &size, &offset, &align, 536 pack, big_endian); 537 union_size = max(size, union_size); 538 } 539 total_align = max(align, total_align); 540 541 if (!prop) { 542 Py_DECREF(pair); 543 return -1; 544 } 545 if (-1 == PyObject_SetAttr(type, name, prop)) { 546 Py_DECREF(prop); 547 Py_DECREF(pair); 548 return -1; 549 } 550 Py_DECREF(pair); 551 Py_DECREF(prop); 552 } 553#undef realdict 554 555 if (isStruct && !isPacked) { 556 char *ptr = stgdict->format; 557 stgdict->format = _ctypes_alloc_format_string(stgdict->format, "}"); 558 PyMem_Free(ptr); 559 if (stgdict->format == NULL) 560 return -1; 561 } 562 563 if (!isStruct) 564 size = union_size; 565 566 /* Adjust the size according to the alignment requirements */ 567 size = ((size + total_align - 1) / total_align) * total_align; 568 569 stgdict->ffi_type_pointer.alignment = Py_SAFE_DOWNCAST(total_align, 570 Py_ssize_t, 571 unsigned short); 572 stgdict->ffi_type_pointer.size = size; 573 574 stgdict->size = size; 575 stgdict->align = total_align; 576 stgdict->length = len; /* ADD ffi_ofs? */ 577 578 /* We did check that this flag was NOT set above, it must not 579 have been set until now. */ 580 if (stgdict->flags & DICTFLAG_FINAL) { 581 PyErr_SetString(PyExc_AttributeError, 582 "Structure or union cannot contain itself"); 583 return -1; 584 } 585 stgdict->flags |= DICTFLAG_FINAL; 586 587 return MakeAnonFields(type); 588} 589