/Modules/_ctypes/stgdict.c

http://unladen-swallow.googlecode.com/ · C · 575 lines · 478 code · 52 blank · 45 comment · 98 complexity · 0b2d4e383f644aff8157d289ee1eaffc MD5 · raw file

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