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 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 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 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 int 52 PyCStgDict_clone(StgDictObject *dst, StgDictObject *src) 53 { 54 char *d, *s; 55 Py_ssize_t size; 56 57 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; 64 65 d = (char *)dst; 66 s = (char *)src; 67 memcpy(d + sizeof(PyDictObject), 68 s + sizeof(PyDictObject), 69 sizeof(StgDictObject) - sizeof(PyDictObject)); 70 71 Py_XINCREF(dst->proto); 72 Py_XINCREF(dst->argtypes); 73 Py_XINCREF(dst->converters); 74 Py_XINCREF(dst->restype); 75 Py_XINCREF(dst->checker); 76 77 if (src->format) { 78 dst->format = PyMem_Malloc(strlen(src->format) + 1); 79 if (dst->format == NULL) { 80 PyErr_NoMemory(); 81 return -1; 82 } 83 strcpy(dst->format, src->format); 84 } 85 if (src->shape) { 86 dst->shape = PyMem_Malloc(sizeof(Py_ssize_t) * src->ndim); 87 if (dst->shape == NULL) { 88 PyErr_NoMemory(); 89 return -1; 90 } 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 109 PyTypeObject 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! */ 152 StgDictObject * 153 PyType_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 */ 172 StgDictObject * 173 PyObject_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 */ 187 static int 188 MakeFields(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 */ 265 static int 266 MakeAnonFields(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 */ 311 int 312 PyCStructUnionType_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_AsInt(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_New(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 if (basedict->length > 0) { 399 memcpy(stgdict->ffi_type_pointer.elements, 400 basedict->ffi_type_pointer.elements, 401 sizeof(ffi_type *) * (basedict->length)); 402 } 403 ffi_ofs = basedict->length; 404 } else { 405 offset = 0; 406 size = 0; 407 align = 0; 408 union_size = 0; 409 total_align = 1; 410 stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT; 411 stgdict->ffi_type_pointer.elements = PyMem_New(ffi_type *, len + 1); 412 if (stgdict->ffi_type_pointer.elements == NULL) { 413 PyErr_NoMemory(); 414 return -1; 415 } 416 memset(stgdict->ffi_type_pointer.elements, 0, 417 sizeof(ffi_type *) * (len + 1)); 418 ffi_ofs = 0; 419 } 420 421 assert(stgdict->format == NULL); 422 if (isStruct && !isPacked) { 423 stgdict->format = _ctypes_alloc_format_string(NULL, "T{"); 424 } else { 425 /* PEP3118 doesn't support union, or packed structures (well, 426 only standard packing, but we dont support the pep for 427 that). Use 'B' for bytes. */ 428 stgdict->format = _ctypes_alloc_format_string(NULL, "B"); 429 } 430 431 #define realdict ((PyObject *)&stgdict->dict) 432 for (i = 0; i < len; ++i) { 433 PyObject *name = NULL, *desc = NULL; 434 PyObject *pair = PySequence_GetItem(fields, i); 435 PyObject *prop; 436 StgDictObject *dict; 437 int bitsize = 0; 438 439 if (!pair || !PyArg_ParseTuple(pair, "OO|i", &name, &desc, &bitsize)) { 440 PyErr_SetString(PyExc_AttributeError, 441 "'_fields_' must be a sequence of pairs"); 442 Py_XDECREF(pair); 443 return -1; 444 } 445 dict = PyType_stgdict(desc); 446 if (dict == NULL) { 447 Py_DECREF(pair); 448 PyErr_Format(PyExc_TypeError, 449 #if (PY_VERSION_HEX < 0x02050000) 450 /* Compatibility no longer strictly required */ 451 "second item in _fields_ tuple (index %d) must be a C type", 452 #else 453 "second item in _fields_ tuple (index %zd) must be a C type", 454 #endif 455 i); 456 return -1; 457 } 458 stgdict->ffi_type_pointer.elements[ffi_ofs + i] = &dict->ffi_type_pointer; 459 if (dict->flags & (TYPEFLAG_ISPOINTER | TYPEFLAG_HASPOINTER)) 460 stgdict->flags |= TYPEFLAG_HASPOINTER; 461 dict->flags |= DICTFLAG_FINAL; /* mark field type final */ 462 if (PyTuple_Size(pair) == 3) { /* bits specified */ 463 switch(dict->ffi_type_pointer.type) { 464 case FFI_TYPE_UINT8: 465 case FFI_TYPE_UINT16: 466 case FFI_TYPE_UINT32: 467 case FFI_TYPE_SINT64: 468 case FFI_TYPE_UINT64: 469 break; 470 471 case FFI_TYPE_SINT8: 472 case FFI_TYPE_SINT16: 473 case FFI_TYPE_SINT32: 474 if (dict->getfunc != _ctypes_get_fielddesc("c")->getfunc 475 #ifdef CTYPES_UNICODE 476 && dict->getfunc != _ctypes_get_fielddesc("u")->getfunc 477 #endif 478 ) 479 break; 480 /* else fall through */ 481 default: 482 PyErr_Format(PyExc_TypeError, 483 "bit fields not allowed for type %s", 484 ((PyTypeObject *)desc)->tp_name); 485 Py_DECREF(pair); 486 return -1; 487 } 488 if (bitsize <= 0 || bitsize > dict->size * 8) { 489 PyErr_SetString(PyExc_ValueError, 490 "number of bits invalid for bit field"); 491 Py_DECREF(pair); 492 return -1; 493 } 494 } else 495 bitsize = 0; 496 if (isStruct && !isPacked) { 497 char *fieldfmt = dict->format ? dict->format : "B"; 498 char *fieldname = PyString_AsString(name); 499 char *ptr; 500 Py_ssize_t len; 501 char *buf; 502 503 if (fieldname == NULL) 504 { 505 PyErr_Format(PyExc_TypeError, 506 "structure field name must be string not %s", 507 name->ob_type->tp_name); 508 509 Py_DECREF(pair); 510 return -1; 511 } 512 513 len = strlen(fieldname) + strlen(fieldfmt); 514 515 buf = PyMem_Malloc(len + 2 + 1); 516 if (buf == NULL) { 517 Py_DECREF(pair); 518 PyErr_NoMemory(); 519 return -1; 520 } 521 sprintf(buf, "%s:%s:", fieldfmt, fieldname); 522 523 ptr = stgdict->format; 524 if (dict->shape != NULL) { 525 stgdict->format = _ctypes_alloc_format_string_with_shape( 526 dict->ndim, dict->shape, stgdict->format, buf); 527 } else { 528 stgdict->format = _ctypes_alloc_format_string(stgdict->format, buf); 529 } 530 PyMem_Free(ptr); 531 PyMem_Free(buf); 532 533 if (stgdict->format == NULL) { 534 Py_DECREF(pair); 535 return -1; 536 } 537 } 538 if (isStruct) { 539 prop = PyCField_FromDesc(desc, i, 540 &field_size, bitsize, &bitofs, 541 &size, &offset, &align, 542 pack, big_endian); 543 } else /* union */ { 544 size = 0; 545 offset = 0; 546 align = 0; 547 prop = PyCField_FromDesc(desc, i, 548 &field_size, bitsize, &bitofs, 549 &size, &offset, &align, 550 pack, big_endian); 551 union_size = max(size, union_size); 552 } 553 total_align = max(align, total_align); 554 555 if (!prop) { 556 Py_DECREF(pair); 557 return -1; 558 } 559 if (-1 == PyObject_SetAttr(type, name, prop)) { 560 Py_DECREF(prop); 561 Py_DECREF(pair); 562 return -1; 563 } 564 Py_DECREF(pair); 565 Py_DECREF(prop); 566 } 567 #undef realdict 568 569 if (isStruct && !isPacked) { 570 char *ptr = stgdict->format; 571 stgdict->format = _ctypes_alloc_format_string(stgdict->format, "}"); 572 PyMem_Free(ptr); 573 if (stgdict->format == NULL) 574 return -1; 575 } 576 577 if (!isStruct) 578 size = union_size; 579 580 /* Adjust the size according to the alignment requirements */ 581 size = ((size + total_align - 1) / total_align) * total_align; 582 583 stgdict->ffi_type_pointer.alignment = Py_SAFE_DOWNCAST(total_align, 584 Py_ssize_t, 585 unsigned short); 586 stgdict->ffi_type_pointer.size = size; 587 588 stgdict->size = size; 589 stgdict->align = total_align; 590 stgdict->length = len; /* ADD ffi_ofs? */ 591 592 /* We did check that this flag was NOT set above, it must not 593 have been set until now. */ 594 if (stgdict->flags & DICTFLAG_FINAL) { 595 PyErr_SetString(PyExc_AttributeError, 596 "Structure or union cannot contain itself"); 597 return -1; 598 } 599 stgdict->flags |= DICTFLAG_FINAL; 600 601 return MakeAnonFields(type); 602 } 603