Line data Source code
1 : /*
2 : ToDo:
3 :
4 : Get rid of the checker (and also the converters) field in PyCFuncPtrObject and
5 : StgDictObject, and replace them by slot functions in StgDictObject.
6 :
7 : think about a buffer-like object (memory? bytes?)
8 :
9 : Should POINTER(c_char) and POINTER(c_wchar) have a .value property?
10 : What about c_char and c_wchar arrays then?
11 :
12 : Add from_mmap, from_file, from_string metaclass methods.
13 :
14 : Maybe we can get away with from_file (calls read) and with a from_buffer
15 : method?
16 :
17 : And what about the to_mmap, to_file, to_str(?) methods? They would clobber
18 : the namespace, probably. So, functions instead? And we already have memmove...
19 : */
20 :
21 : /*
22 :
23 : Name methods, members, getsets
24 : ==============================================================================
25 :
26 : PyCStructType_Type __new__(), from_address(), __mul__(), from_param()
27 : UnionType_Type __new__(), from_address(), __mul__(), from_param()
28 : PyCPointerType_Type __new__(), from_address(), __mul__(), from_param(), set_type()
29 : PyCArrayType_Type __new__(), from_address(), __mul__(), from_param()
30 : PyCSimpleType_Type __new__(), from_address(), __mul__(), from_param()
31 :
32 : PyCData_Type
33 : Struct_Type __new__(), __init__()
34 : PyCPointer_Type __new__(), __init__(), _as_parameter_, contents
35 : PyCArray_Type __new__(), __init__(), _as_parameter_, __get/setitem__(), __len__()
36 : Simple_Type __new__(), __init__(), _as_parameter_
37 :
38 : PyCField_Type
39 : PyCStgDict_Type
40 :
41 : ==============================================================================
42 :
43 : class methods
44 : -------------
45 :
46 : It has some similarity to the byref() construct compared to pointer()
47 : from_address(addr)
48 : - construct an instance from a given memory block (sharing this memory block)
49 :
50 : from_param(obj)
51 : - typecheck and convert a Python object into a C function call parameter
52 : the result may be an instance of the type, or an integer or tuple
53 : (typecode, value[, obj])
54 :
55 : instance methods/properties
56 : ---------------------------
57 :
58 : _as_parameter_
59 : - convert self into a C function call parameter
60 : This is either an integer, or a 3-tuple (typecode, value, obj)
61 :
62 : functions
63 : ---------
64 :
65 : sizeof(cdata)
66 : - return the number of bytes the buffer contains
67 :
68 : sizeof(ctype)
69 : - return the number of bytes the buffer of an instance would contain
70 :
71 : byref(cdata)
72 :
73 : addressof(cdata)
74 :
75 : pointer(cdata)
76 :
77 : POINTER(ctype)
78 :
79 : bytes(cdata)
80 : - return the buffer contents as a sequence of bytes (which is currently a string)
81 :
82 : */
83 :
84 : /*
85 : * PyCStgDict_Type
86 : * PyCStructType_Type
87 : * UnionType_Type
88 : * PyCPointerType_Type
89 : * PyCArrayType_Type
90 : * PyCSimpleType_Type
91 : *
92 : * PyCData_Type
93 : * Struct_Type
94 : * Union_Type
95 : * PyCArray_Type
96 : * Simple_Type
97 : * PyCPointer_Type
98 : * PyCField_Type
99 : *
100 : */
101 :
102 : #define PY_SSIZE_T_CLEAN
103 :
104 : #include "Python.h"
105 : #include "structmember.h"
106 :
107 : #include <ffi.h>
108 : #ifdef MS_WIN32
109 : #include <windows.h>
110 : #include <malloc.h>
111 : #ifndef IS_INTRESOURCE
112 : #define IS_INTRESOURCE(x) (((size_t)(x) >> 16) == 0)
113 : #endif
114 : # ifdef _WIN32_WCE
115 : /* Unlike desktop Windows, WinCE has both W and A variants of
116 : GetProcAddress, but the default W version is not what we want */
117 : # undef GetProcAddress
118 : # define GetProcAddress GetProcAddressA
119 : # endif
120 : #else
121 : #include "ctypes_dlfcn.h"
122 : #endif
123 : #include "ctypes.h"
124 :
125 : PyObject *PyExc_ArgError;
126 :
127 : /* This dict maps ctypes types to POINTER types */
128 : PyObject *_ctypes_ptrtype_cache;
129 :
130 : static PyTypeObject Simple_Type;
131 :
132 : /* a callable object used for unpickling */
133 : static PyObject *_unpickle;
134 :
135 :
136 :
137 : /****************************************************************/
138 :
139 : typedef struct {
140 : PyObject_HEAD
141 : PyObject *key;
142 : PyObject *dict;
143 : } DictRemoverObject;
144 :
145 : static void
146 0 : _DictRemover_dealloc(PyObject *_self)
147 : {
148 0 : DictRemoverObject *self = (DictRemoverObject *)_self;
149 0 : Py_XDECREF(self->key);
150 0 : Py_XDECREF(self->dict);
151 0 : Py_TYPE(self)->tp_free(_self);
152 0 : }
153 :
154 : static PyObject *
155 0 : _DictRemover_call(PyObject *_self, PyObject *args, PyObject *kw)
156 : {
157 0 : DictRemoverObject *self = (DictRemoverObject *)_self;
158 0 : if (self->key && self->dict) {
159 0 : if (-1 == PyDict_DelItem(self->dict, self->key))
160 : /* XXX Error context */
161 0 : PyErr_WriteUnraisable(Py_None);
162 0 : Py_DECREF(self->key);
163 0 : self->key = NULL;
164 0 : Py_DECREF(self->dict);
165 0 : self->dict = NULL;
166 : }
167 0 : Py_INCREF(Py_None);
168 0 : return Py_None;
169 : }
170 :
171 : static PyTypeObject DictRemover_Type = {
172 : PyVarObject_HEAD_INIT(NULL, 0)
173 : "_ctypes.DictRemover", /* tp_name */
174 : sizeof(DictRemoverObject), /* tp_basicsize */
175 : 0, /* tp_itemsize */
176 : _DictRemover_dealloc, /* tp_dealloc */
177 : 0, /* tp_print */
178 : 0, /* tp_getattr */
179 : 0, /* tp_setattr */
180 : 0, /* tp_reserved */
181 : 0, /* tp_repr */
182 : 0, /* tp_as_number */
183 : 0, /* tp_as_sequence */
184 : 0, /* tp_as_mapping */
185 : 0, /* tp_hash */
186 : _DictRemover_call, /* tp_call */
187 : 0, /* tp_str */
188 : 0, /* tp_getattro */
189 : 0, /* tp_setattro */
190 : 0, /* tp_as_buffer */
191 : /* XXX should participate in GC? */
192 : Py_TPFLAGS_DEFAULT, /* tp_flags */
193 : "deletes a key from a dictionary", /* tp_doc */
194 : 0, /* tp_traverse */
195 : 0, /* tp_clear */
196 : 0, /* tp_richcompare */
197 : 0, /* tp_weaklistoffset */
198 : 0, /* tp_iter */
199 : 0, /* tp_iternext */
200 : 0, /* tp_methods */
201 : 0, /* tp_members */
202 : 0, /* tp_getset */
203 : 0, /* tp_base */
204 : 0, /* tp_dict */
205 : 0, /* tp_descr_get */
206 : 0, /* tp_descr_set */
207 : 0, /* tp_dictoffset */
208 : 0, /* tp_init */
209 : 0, /* tp_alloc */
210 : 0, /* tp_new */
211 : 0, /* tp_free */
212 : };
213 :
214 : int
215 0 : PyDict_SetItemProxy(PyObject *dict, PyObject *key, PyObject *item)
216 : {
217 : PyObject *obj;
218 : DictRemoverObject *remover;
219 : PyObject *proxy;
220 : int result;
221 :
222 0 : obj = PyObject_CallObject((PyObject *)&DictRemover_Type, NULL);
223 0 : if (obj == NULL)
224 0 : return -1;
225 :
226 0 : remover = (DictRemoverObject *)obj;
227 : assert(remover->key == NULL);
228 : assert(remover->dict == NULL);
229 0 : Py_INCREF(key);
230 0 : remover->key = key;
231 0 : Py_INCREF(dict);
232 0 : remover->dict = dict;
233 :
234 0 : proxy = PyWeakref_NewProxy(item, obj);
235 0 : Py_DECREF(obj);
236 0 : if (proxy == NULL)
237 0 : return -1;
238 :
239 0 : result = PyDict_SetItem(dict, key, proxy);
240 0 : Py_DECREF(proxy);
241 0 : return result;
242 : }
243 :
244 : PyObject *
245 0 : PyDict_GetItemProxy(PyObject *dict, PyObject *key)
246 : {
247 : PyObject *result;
248 0 : PyObject *item = PyDict_GetItem(dict, key);
249 :
250 0 : if (item == NULL)
251 0 : return NULL;
252 0 : if (!PyWeakref_CheckProxy(item))
253 0 : return item;
254 0 : result = PyWeakref_GET_OBJECT(item);
255 0 : if (result == Py_None)
256 0 : return NULL;
257 0 : return result;
258 : }
259 :
260 : /******************************************************************/
261 : /*
262 : Allocate a memory block for a pep3118 format string, copy prefix (if
263 : non-null) and suffix into it. Returns NULL on failure, with the error
264 : indicator set. If called with a suffix of NULL the error indicator must
265 : already be set.
266 : */
267 : char *
268 0 : _ctypes_alloc_format_string(const char *prefix, const char *suffix)
269 : {
270 : size_t len;
271 : char *result;
272 :
273 0 : if (suffix == NULL) {
274 : assert(PyErr_Occurred());
275 0 : return NULL;
276 : }
277 0 : len = strlen(suffix);
278 0 : if (prefix)
279 0 : len += strlen(prefix);
280 0 : result = PyMem_Malloc(len + 1);
281 0 : if (result == NULL)
282 0 : return NULL;
283 0 : if (prefix)
284 0 : strcpy(result, prefix);
285 : else
286 0 : result[0] = '\0';
287 0 : strcat(result, suffix);
288 0 : return result;
289 : }
290 :
291 : /*
292 : PyCStructType_Type - a meta type/class. Creating a new class using this one as
293 : __metaclass__ will call the contructor StructUnionType_new. It replaces the
294 : tp_dict member with a new instance of StgDict, and initializes the C
295 : accessible fields somehow.
296 : */
297 :
298 : static PyCArgObject *
299 0 : StructUnionType_paramfunc(CDataObject *self)
300 : {
301 : PyCArgObject *parg;
302 : StgDictObject *stgdict;
303 :
304 0 : parg = PyCArgObject_new();
305 0 : if (parg == NULL)
306 0 : return NULL;
307 :
308 0 : parg->tag = 'V';
309 0 : stgdict = PyObject_stgdict((PyObject *)self);
310 : assert(stgdict); /* Cannot be NULL for structure/union instances */
311 0 : parg->pffi_type = &stgdict->ffi_type_pointer;
312 : /* For structure parameters (by value), parg->value doesn't contain the structure
313 : data itself, instead parg->value.p *points* to the structure's data
314 : See also _ctypes.c, function _call_function_pointer().
315 : */
316 0 : parg->value.p = self->b_ptr;
317 0 : parg->size = self->b_size;
318 0 : Py_INCREF(self);
319 0 : parg->obj = (PyObject *)self;
320 0 : return parg;
321 : }
322 :
323 : static PyObject *
324 0 : StructUnionType_new(PyTypeObject *type, PyObject *args, PyObject *kwds, int isStruct)
325 : {
326 : PyTypeObject *result;
327 : PyObject *fields;
328 : StgDictObject *dict;
329 :
330 : /* create the new instance (which is a class,
331 : since we are a metatype!) */
332 0 : result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds);
333 0 : if (!result)
334 0 : return NULL;
335 :
336 : /* keep this for bw compatibility */
337 0 : if (PyDict_GetItemString(result->tp_dict, "_abstract_"))
338 0 : return (PyObject *)result;
339 :
340 0 : dict = (StgDictObject *)PyObject_CallObject((PyObject *)&PyCStgDict_Type, NULL);
341 0 : if (!dict) {
342 0 : Py_DECREF(result);
343 0 : return NULL;
344 : }
345 : /* replace the class dict by our updated stgdict, which holds info
346 : about storage requirements of the instances */
347 0 : if (-1 == PyDict_Update((PyObject *)dict, result->tp_dict)) {
348 0 : Py_DECREF(result);
349 0 : Py_DECREF((PyObject *)dict);
350 0 : return NULL;
351 : }
352 0 : Py_DECREF(result->tp_dict);
353 0 : result->tp_dict = (PyObject *)dict;
354 0 : dict->format = _ctypes_alloc_format_string(NULL, "B");
355 0 : if (dict->format == NULL) {
356 0 : Py_DECREF(result);
357 0 : return NULL;
358 : }
359 :
360 0 : dict->paramfunc = StructUnionType_paramfunc;
361 :
362 0 : fields = PyDict_GetItemString((PyObject *)dict, "_fields_");
363 0 : if (!fields) {
364 0 : StgDictObject *basedict = PyType_stgdict((PyObject *)result->tp_base);
365 :
366 0 : if (basedict == NULL)
367 0 : return (PyObject *)result;
368 : /* copy base dict */
369 0 : if (-1 == PyCStgDict_clone(dict, basedict)) {
370 0 : Py_DECREF(result);
371 0 : return NULL;
372 : }
373 0 : dict->flags &= ~DICTFLAG_FINAL; /* clear the 'final' flag in the subclass dict */
374 0 : basedict->flags |= DICTFLAG_FINAL; /* set the 'final' flag in the baseclass dict */
375 0 : return (PyObject *)result;
376 : }
377 :
378 0 : if (-1 == PyObject_SetAttrString((PyObject *)result, "_fields_", fields)) {
379 0 : Py_DECREF(result);
380 0 : return NULL;
381 : }
382 0 : return (PyObject *)result;
383 : }
384 :
385 : static PyObject *
386 0 : PyCStructType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
387 : {
388 0 : return StructUnionType_new(type, args, kwds, 1);
389 : }
390 :
391 : static PyObject *
392 0 : UnionType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
393 : {
394 0 : return StructUnionType_new(type, args, kwds, 0);
395 : }
396 :
397 : static char from_address_doc[] =
398 : "C.from_address(integer) -> C instance\naccess a C instance at the specified address";
399 :
400 : static PyObject *
401 0 : CDataType_from_address(PyObject *type, PyObject *value)
402 : {
403 : void *buf;
404 0 : if (!PyLong_Check(value)) {
405 0 : PyErr_SetString(PyExc_TypeError,
406 : "integer expected");
407 0 : return NULL;
408 : }
409 0 : buf = (void *)PyLong_AsVoidPtr(value);
410 0 : if (PyErr_Occurred())
411 0 : return NULL;
412 0 : return PyCData_AtAddress(type, buf);
413 : }
414 :
415 : static char from_buffer_doc[] =
416 : "C.from_buffer(object, offset=0) -> C instance\ncreate a C instance from a writeable buffer";
417 :
418 : static int
419 : KeepRef(CDataObject *target, Py_ssize_t index, PyObject *keep);
420 :
421 : static PyObject *
422 0 : CDataType_from_buffer(PyObject *type, PyObject *args)
423 : {
424 : void *buffer;
425 : Py_ssize_t buffer_len;
426 0 : Py_ssize_t offset = 0;
427 : PyObject *obj, *result;
428 0 : StgDictObject *dict = PyType_stgdict(type);
429 : assert (dict);
430 :
431 0 : if (!PyArg_ParseTuple(args,
432 : #if (PY_VERSION_HEX < 0x02050000)
433 : "O|i:from_buffer",
434 : #else
435 : "O|n:from_buffer",
436 : #endif
437 : &obj, &offset))
438 0 : return NULL;
439 :
440 0 : if (-1 == PyObject_AsWriteBuffer(obj, &buffer, &buffer_len))
441 0 : return NULL;
442 :
443 0 : if (offset < 0) {
444 0 : PyErr_SetString(PyExc_ValueError,
445 : "offset cannot be negative");
446 0 : return NULL;
447 : }
448 0 : if (dict->size > buffer_len - offset) {
449 0 : PyErr_Format(PyExc_ValueError,
450 : #if (PY_VERSION_HEX < 0x02050000)
451 : "Buffer size too small (%d instead of at least %d bytes)",
452 : #else
453 : "Buffer size too small (%zd instead of at least %zd bytes)",
454 : #endif
455 0 : buffer_len, dict->size + offset);
456 0 : return NULL;
457 : }
458 :
459 0 : result = PyCData_AtAddress(type, (char *)buffer + offset);
460 0 : if (result == NULL)
461 0 : return NULL;
462 :
463 0 : Py_INCREF(obj);
464 0 : if (-1 == KeepRef((CDataObject *)result, -1, obj)) {
465 0 : Py_DECREF(result);
466 0 : return NULL;
467 : }
468 0 : return result;
469 : }
470 :
471 : static char from_buffer_copy_doc[] =
472 : "C.from_buffer_copy(object, offset=0) -> C instance\ncreate a C instance from a readable buffer";
473 :
474 : static PyObject *
475 : GenericPyCData_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
476 :
477 : static PyObject *
478 0 : CDataType_from_buffer_copy(PyObject *type, PyObject *args)
479 : {
480 : const void *buffer;
481 : Py_ssize_t buffer_len;
482 0 : Py_ssize_t offset = 0;
483 : PyObject *obj, *result;
484 0 : StgDictObject *dict = PyType_stgdict(type);
485 : assert (dict);
486 :
487 0 : if (!PyArg_ParseTuple(args,
488 : #if (PY_VERSION_HEX < 0x02050000)
489 : "O|i:from_buffer",
490 : #else
491 : "O|n:from_buffer",
492 : #endif
493 : &obj, &offset))
494 0 : return NULL;
495 :
496 0 : if (-1 == PyObject_AsReadBuffer(obj, (const void**)&buffer, &buffer_len))
497 0 : return NULL;
498 :
499 0 : if (offset < 0) {
500 0 : PyErr_SetString(PyExc_ValueError,
501 : "offset cannot be negative");
502 0 : return NULL;
503 : }
504 :
505 0 : if (dict->size > buffer_len - offset) {
506 0 : PyErr_Format(PyExc_ValueError,
507 : #if (PY_VERSION_HEX < 0x02050000)
508 : "Buffer size too small (%d instead of at least %d bytes)",
509 : #else
510 : "Buffer size too small (%zd instead of at least %zd bytes)",
511 : #endif
512 0 : buffer_len, dict->size + offset);
513 0 : return NULL;
514 : }
515 :
516 0 : result = GenericPyCData_new((PyTypeObject *)type, NULL, NULL);
517 0 : if (result == NULL)
518 0 : return NULL;
519 0 : memcpy(((CDataObject *)result)->b_ptr,
520 0 : (char *)buffer+offset, dict->size);
521 0 : return result;
522 : }
523 :
524 : static char in_dll_doc[] =
525 : "C.in_dll(dll, name) -> C instance\naccess a C instance in a dll";
526 :
527 : static PyObject *
528 0 : CDataType_in_dll(PyObject *type, PyObject *args)
529 : {
530 : PyObject *dll;
531 : char *name;
532 : PyObject *obj;
533 : void *handle;
534 : void *address;
535 :
536 0 : if (!PyArg_ParseTuple(args, "Os:in_dll", &dll, &name))
537 0 : return NULL;
538 :
539 0 : obj = PyObject_GetAttrString(dll, "_handle");
540 0 : if (!obj)
541 0 : return NULL;
542 0 : if (!PyLong_Check(obj)) {
543 0 : PyErr_SetString(PyExc_TypeError,
544 : "the _handle attribute of the second argument must be an integer");
545 0 : Py_DECREF(obj);
546 0 : return NULL;
547 : }
548 0 : handle = (void *)PyLong_AsVoidPtr(obj);
549 0 : Py_DECREF(obj);
550 0 : if (PyErr_Occurred()) {
551 0 : PyErr_SetString(PyExc_ValueError,
552 : "could not convert the _handle attribute to a pointer");
553 0 : return NULL;
554 : }
555 :
556 : #ifdef MS_WIN32
557 : address = (void *)GetProcAddress(handle, name);
558 : if (!address) {
559 : PyErr_Format(PyExc_ValueError,
560 : "symbol '%s' not found",
561 : name);
562 : return NULL;
563 : }
564 : #else
565 0 : address = (void *)ctypes_dlsym(handle, name);
566 0 : if (!address) {
567 : #ifdef __CYGWIN__
568 : /* dlerror() isn't very helpful on cygwin */
569 : PyErr_Format(PyExc_ValueError,
570 : "symbol '%s' not found (%s) ",
571 : name);
572 : #else
573 0 : PyErr_SetString(PyExc_ValueError, ctypes_dlerror());
574 : #endif
575 0 : return NULL;
576 : }
577 : #endif
578 0 : return PyCData_AtAddress(type, address);
579 : }
580 :
581 : static char from_param_doc[] =
582 : "Convert a Python object into a function call parameter.";
583 :
584 : static PyObject *
585 0 : CDataType_from_param(PyObject *type, PyObject *value)
586 : {
587 : PyObject *as_parameter;
588 0 : int res = PyObject_IsInstance(value, type);
589 0 : if (res == -1)
590 0 : return NULL;
591 0 : if (res) {
592 0 : Py_INCREF(value);
593 0 : return value;
594 : }
595 0 : if (PyCArg_CheckExact(value)) {
596 0 : PyCArgObject *p = (PyCArgObject *)value;
597 0 : PyObject *ob = p->obj;
598 : const char *ob_name;
599 : StgDictObject *dict;
600 0 : dict = PyType_stgdict(type);
601 :
602 : /* If we got a PyCArgObject, we must check if the object packed in it
603 : is an instance of the type's dict->proto */
604 0 : if(dict && ob) {
605 0 : res = PyObject_IsInstance(ob, dict->proto);
606 0 : if (res == -1)
607 0 : return NULL;
608 0 : if (res) {
609 0 : Py_INCREF(value);
610 0 : return value;
611 : }
612 : }
613 0 : ob_name = (ob) ? Py_TYPE(ob)->tp_name : "???";
614 0 : PyErr_Format(PyExc_TypeError,
615 : "expected %s instance instead of pointer to %s",
616 : ((PyTypeObject *)type)->tp_name, ob_name);
617 0 : return NULL;
618 : }
619 :
620 0 : as_parameter = PyObject_GetAttrString(value, "_as_parameter_");
621 0 : if (as_parameter) {
622 0 : value = CDataType_from_param(type, as_parameter);
623 0 : Py_DECREF(as_parameter);
624 0 : return value;
625 : }
626 0 : PyErr_Format(PyExc_TypeError,
627 : "expected %s instance instead of %s",
628 : ((PyTypeObject *)type)->tp_name,
629 0 : Py_TYPE(value)->tp_name);
630 0 : return NULL;
631 : }
632 :
633 : static PyMethodDef CDataType_methods[] = {
634 : { "from_param", CDataType_from_param, METH_O, from_param_doc },
635 : { "from_address", CDataType_from_address, METH_O, from_address_doc },
636 : { "from_buffer", CDataType_from_buffer, METH_VARARGS, from_buffer_doc, },
637 : { "from_buffer_copy", CDataType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, },
638 : { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc },
639 : { NULL, NULL },
640 : };
641 :
642 : static PyObject *
643 0 : CDataType_repeat(PyObject *self, Py_ssize_t length)
644 : {
645 0 : if (length < 0)
646 0 : return PyErr_Format(PyExc_ValueError,
647 : "Array length must be >= 0, not %zd",
648 : length);
649 0 : return PyCArrayType_from_ctype(self, length);
650 : }
651 :
652 : static PySequenceMethods CDataType_as_sequence = {
653 : 0, /* inquiry sq_length; */
654 : 0, /* binaryfunc sq_concat; */
655 : CDataType_repeat, /* intargfunc sq_repeat; */
656 : 0, /* intargfunc sq_item; */
657 : 0, /* intintargfunc sq_slice; */
658 : 0, /* intobjargproc sq_ass_item; */
659 : 0, /* intintobjargproc sq_ass_slice; */
660 : 0, /* objobjproc sq_contains; */
661 :
662 : 0, /* binaryfunc sq_inplace_concat; */
663 : 0, /* intargfunc sq_inplace_repeat; */
664 : };
665 :
666 : static int
667 0 : CDataType_clear(PyTypeObject *self)
668 : {
669 0 : StgDictObject *dict = PyType_stgdict((PyObject *)self);
670 0 : if (dict)
671 0 : Py_CLEAR(dict->proto);
672 0 : return PyType_Type.tp_clear((PyObject *)self);
673 : }
674 :
675 : static int
676 0 : CDataType_traverse(PyTypeObject *self, visitproc visit, void *arg)
677 : {
678 0 : StgDictObject *dict = PyType_stgdict((PyObject *)self);
679 0 : if (dict)
680 0 : Py_VISIT(dict->proto);
681 0 : return PyType_Type.tp_traverse((PyObject *)self, visit, arg);
682 : }
683 :
684 : static int
685 0 : PyCStructType_setattro(PyObject *self, PyObject *key, PyObject *value)
686 : {
687 : /* XXX Should we disallow deleting _fields_? */
688 0 : if (-1 == PyType_Type.tp_setattro(self, key, value))
689 0 : return -1;
690 :
691 0 : if (value && PyUnicode_Check(key) &&
692 : /* XXX struni _PyUnicode_AsString can fail (also in other places)! */
693 0 : 0 == strcmp(_PyUnicode_AsString(key), "_fields_"))
694 0 : return PyCStructUnionType_update_stgdict(self, value, 1);
695 0 : return 0;
696 : }
697 :
698 :
699 : static int
700 0 : UnionType_setattro(PyObject *self, PyObject *key, PyObject *value)
701 : {
702 : /* XXX Should we disallow deleting _fields_? */
703 0 : if (-1 == PyObject_GenericSetAttr(self, key, value))
704 0 : return -1;
705 :
706 0 : if (PyUnicode_Check(key) &&
707 0 : 0 == strcmp(_PyUnicode_AsString(key), "_fields_"))
708 0 : return PyCStructUnionType_update_stgdict(self, value, 0);
709 0 : return 0;
710 : }
711 :
712 :
713 : PyTypeObject PyCStructType_Type = {
714 : PyVarObject_HEAD_INIT(NULL, 0)
715 : "_ctypes.PyCStructType", /* tp_name */
716 : 0, /* tp_basicsize */
717 : 0, /* tp_itemsize */
718 : 0, /* tp_dealloc */
719 : 0, /* tp_print */
720 : 0, /* tp_getattr */
721 : 0, /* tp_setattr */
722 : 0, /* tp_reserved */
723 : 0, /* tp_repr */
724 : 0, /* tp_as_number */
725 : &CDataType_as_sequence, /* tp_as_sequence */
726 : 0, /* tp_as_mapping */
727 : 0, /* tp_hash */
728 : 0, /* tp_call */
729 : 0, /* tp_str */
730 : 0, /* tp_getattro */
731 : PyCStructType_setattro, /* tp_setattro */
732 : 0, /* tp_as_buffer */
733 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
734 : "metatype for the CData Objects", /* tp_doc */
735 : (traverseproc)CDataType_traverse, /* tp_traverse */
736 : (inquiry)CDataType_clear, /* tp_clear */
737 : 0, /* tp_richcompare */
738 : 0, /* tp_weaklistoffset */
739 : 0, /* tp_iter */
740 : 0, /* tp_iternext */
741 : CDataType_methods, /* tp_methods */
742 : 0, /* tp_members */
743 : 0, /* tp_getset */
744 : 0, /* tp_base */
745 : 0, /* tp_dict */
746 : 0, /* tp_descr_get */
747 : 0, /* tp_descr_set */
748 : 0, /* tp_dictoffset */
749 : 0, /* tp_init */
750 : 0, /* tp_alloc */
751 : PyCStructType_new, /* tp_new */
752 : 0, /* tp_free */
753 : };
754 :
755 : static PyTypeObject UnionType_Type = {
756 : PyVarObject_HEAD_INIT(NULL, 0)
757 : "_ctypes.UnionType", /* tp_name */
758 : 0, /* tp_basicsize */
759 : 0, /* tp_itemsize */
760 : 0, /* tp_dealloc */
761 : 0, /* tp_print */
762 : 0, /* tp_getattr */
763 : 0, /* tp_setattr */
764 : 0, /* tp_reserved */
765 : 0, /* tp_repr */
766 : 0, /* tp_as_number */
767 : &CDataType_as_sequence, /* tp_as_sequence */
768 : 0, /* tp_as_mapping */
769 : 0, /* tp_hash */
770 : 0, /* tp_call */
771 : 0, /* tp_str */
772 : 0, /* tp_getattro */
773 : UnionType_setattro, /* tp_setattro */
774 : 0, /* tp_as_buffer */
775 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
776 : "metatype for the CData Objects", /* tp_doc */
777 : (traverseproc)CDataType_traverse, /* tp_traverse */
778 : (inquiry)CDataType_clear, /* tp_clear */
779 : 0, /* tp_richcompare */
780 : 0, /* tp_weaklistoffset */
781 : 0, /* tp_iter */
782 : 0, /* tp_iternext */
783 : CDataType_methods, /* tp_methods */
784 : 0, /* tp_members */
785 : 0, /* tp_getset */
786 : 0, /* tp_base */
787 : 0, /* tp_dict */
788 : 0, /* tp_descr_get */
789 : 0, /* tp_descr_set */
790 : 0, /* tp_dictoffset */
791 : 0, /* tp_init */
792 : 0, /* tp_alloc */
793 : UnionType_new, /* tp_new */
794 : 0, /* tp_free */
795 : };
796 :
797 :
798 : /******************************************************************/
799 :
800 : /*
801 :
802 : The PyCPointerType_Type metaclass must ensure that the subclass of Pointer can be
803 : created. It must check for a _type_ attribute in the class. Since are no
804 : runtime created properties, a CField is probably *not* needed ?
805 :
806 : class IntPointer(Pointer):
807 : _type_ = "i"
808 :
809 : The PyCPointer_Type provides the functionality: a contents method/property, a
810 : size property/method, and the sequence protocol.
811 :
812 : */
813 :
814 : static int
815 0 : PyCPointerType_SetProto(StgDictObject *stgdict, PyObject *proto)
816 : {
817 0 : if (!proto || !PyType_Check(proto)) {
818 0 : PyErr_SetString(PyExc_TypeError,
819 : "_type_ must be a type");
820 0 : return -1;
821 : }
822 0 : if (!PyType_stgdict(proto)) {
823 0 : PyErr_SetString(PyExc_TypeError,
824 : "_type_ must have storage info");
825 0 : return -1;
826 : }
827 0 : Py_INCREF(proto);
828 0 : Py_XDECREF(stgdict->proto);
829 0 : stgdict->proto = proto;
830 0 : return 0;
831 : }
832 :
833 : static PyCArgObject *
834 0 : PyCPointerType_paramfunc(CDataObject *self)
835 : {
836 : PyCArgObject *parg;
837 :
838 0 : parg = PyCArgObject_new();
839 0 : if (parg == NULL)
840 0 : return NULL;
841 :
842 0 : parg->tag = 'P';
843 0 : parg->pffi_type = &ffi_type_pointer;
844 0 : Py_INCREF(self);
845 0 : parg->obj = (PyObject *)self;
846 0 : parg->value.p = *(void **)self->b_ptr;
847 0 : return parg;
848 : }
849 :
850 : static PyObject *
851 0 : PyCPointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
852 : {
853 : PyTypeObject *result;
854 : StgDictObject *stgdict;
855 : PyObject *proto;
856 : PyObject *typedict;
857 :
858 0 : typedict = PyTuple_GetItem(args, 2);
859 0 : if (!typedict)
860 0 : return NULL;
861 : /*
862 : stgdict items size, align, length contain info about pointers itself,
863 : stgdict->proto has info about the pointed to type!
864 : */
865 0 : stgdict = (StgDictObject *)PyObject_CallObject(
866 : (PyObject *)&PyCStgDict_Type, NULL);
867 0 : if (!stgdict)
868 0 : return NULL;
869 0 : stgdict->size = sizeof(void *);
870 0 : stgdict->align = _ctypes_get_fielddesc("P")->pffi_type->alignment;
871 0 : stgdict->length = 1;
872 0 : stgdict->ffi_type_pointer = ffi_type_pointer;
873 0 : stgdict->paramfunc = PyCPointerType_paramfunc;
874 0 : stgdict->flags |= TYPEFLAG_ISPOINTER;
875 :
876 0 : proto = PyDict_GetItemString(typedict, "_type_"); /* Borrowed ref */
877 0 : if (proto && -1 == PyCPointerType_SetProto(stgdict, proto)) {
878 0 : Py_DECREF((PyObject *)stgdict);
879 0 : return NULL;
880 : }
881 :
882 0 : if (proto) {
883 0 : StgDictObject *itemdict = PyType_stgdict(proto);
884 : assert(itemdict);
885 : /* If itemdict->format is NULL, then this is a pointer to an
886 : incomplete type. We create a generic format string
887 : 'pointer to bytes' in this case. XXX Better would be to
888 : fix the format string later...
889 : */
890 0 : stgdict->format = _ctypes_alloc_format_string("&",
891 0 : itemdict->format ? itemdict->format : "B");
892 0 : if (stgdict->format == NULL) {
893 0 : Py_DECREF((PyObject *)stgdict);
894 0 : return NULL;
895 : }
896 : }
897 :
898 : /* create the new instance (which is a class,
899 : since we are a metatype!) */
900 0 : result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds);
901 0 : if (result == NULL) {
902 0 : Py_DECREF((PyObject *)stgdict);
903 0 : return NULL;
904 : }
905 :
906 : /* replace the class dict by our updated spam dict */
907 0 : if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict)) {
908 0 : Py_DECREF(result);
909 0 : Py_DECREF((PyObject *)stgdict);
910 0 : return NULL;
911 : }
912 0 : Py_DECREF(result->tp_dict);
913 0 : result->tp_dict = (PyObject *)stgdict;
914 :
915 0 : return (PyObject *)result;
916 : }
917 :
918 :
919 : static PyObject *
920 0 : PyCPointerType_set_type(PyTypeObject *self, PyObject *type)
921 : {
922 : StgDictObject *dict;
923 :
924 0 : dict = PyType_stgdict((PyObject *)self);
925 : assert(dict);
926 :
927 0 : if (-1 == PyCPointerType_SetProto(dict, type))
928 0 : return NULL;
929 :
930 0 : if (-1 == PyDict_SetItemString((PyObject *)dict, "_type_", type))
931 0 : return NULL;
932 :
933 0 : Py_INCREF(Py_None);
934 0 : return Py_None;
935 : }
936 :
937 : static PyObject *_byref(PyObject *);
938 :
939 : static PyObject *
940 0 : PyCPointerType_from_param(PyObject *type, PyObject *value)
941 : {
942 : StgDictObject *typedict;
943 :
944 0 : if (value == Py_None) {
945 : /* ConvParam will convert to a NULL pointer later */
946 0 : Py_INCREF(value);
947 0 : return value;
948 : }
949 :
950 0 : typedict = PyType_stgdict(type);
951 : assert(typedict); /* Cannot be NULL for pointer types */
952 :
953 : /* If we expect POINTER(<type>), but receive a <type> instance, accept
954 : it by calling byref(<type>).
955 : */
956 0 : switch (PyObject_IsInstance(value, typedict->proto)) {
957 : case 1:
958 0 : Py_INCREF(value); /* _byref steals a refcount */
959 0 : return _byref(value);
960 : case -1:
961 0 : return NULL;
962 : default:
963 0 : break;
964 : }
965 :
966 0 : if (PointerObject_Check(value) || ArrayObject_Check(value)) {
967 : /* Array instances are also pointers when
968 : the item types are the same.
969 : */
970 0 : StgDictObject *v = PyObject_stgdict(value);
971 : assert(v); /* Cannot be NULL for pointer or array objects */
972 0 : if (PyObject_IsSubclass(v->proto, typedict->proto)) {
973 0 : Py_INCREF(value);
974 0 : return value;
975 : }
976 : }
977 0 : return CDataType_from_param(type, value);
978 : }
979 :
980 : static PyMethodDef PyCPointerType_methods[] = {
981 : { "from_address", CDataType_from_address, METH_O, from_address_doc },
982 : { "from_buffer", CDataType_from_buffer, METH_VARARGS, from_buffer_doc, },
983 : { "from_buffer_copy", CDataType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, },
984 : { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc},
985 : { "from_param", (PyCFunction)PyCPointerType_from_param, METH_O, from_param_doc},
986 : { "set_type", (PyCFunction)PyCPointerType_set_type, METH_O },
987 : { NULL, NULL },
988 : };
989 :
990 : PyTypeObject PyCPointerType_Type = {
991 : PyVarObject_HEAD_INIT(NULL, 0)
992 : "_ctypes.PyCPointerType", /* tp_name */
993 : 0, /* tp_basicsize */
994 : 0, /* tp_itemsize */
995 : 0, /* tp_dealloc */
996 : 0, /* tp_print */
997 : 0, /* tp_getattr */
998 : 0, /* tp_setattr */
999 : 0, /* tp_reserved */
1000 : 0, /* tp_repr */
1001 : 0, /* tp_as_number */
1002 : &CDataType_as_sequence, /* tp_as_sequence */
1003 : 0, /* tp_as_mapping */
1004 : 0, /* tp_hash */
1005 : 0, /* tp_call */
1006 : 0, /* tp_str */
1007 : 0, /* tp_getattro */
1008 : 0, /* tp_setattro */
1009 : 0, /* tp_as_buffer */
1010 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1011 : "metatype for the Pointer Objects", /* tp_doc */
1012 : (traverseproc)CDataType_traverse, /* tp_traverse */
1013 : (inquiry)CDataType_clear, /* tp_clear */
1014 : 0, /* tp_richcompare */
1015 : 0, /* tp_weaklistoffset */
1016 : 0, /* tp_iter */
1017 : 0, /* tp_iternext */
1018 : PyCPointerType_methods, /* tp_methods */
1019 : 0, /* tp_members */
1020 : 0, /* tp_getset */
1021 : 0, /* tp_base */
1022 : 0, /* tp_dict */
1023 : 0, /* tp_descr_get */
1024 : 0, /* tp_descr_set */
1025 : 0, /* tp_dictoffset */
1026 : 0, /* tp_init */
1027 : 0, /* tp_alloc */
1028 : PyCPointerType_new, /* tp_new */
1029 : 0, /* tp_free */
1030 : };
1031 :
1032 :
1033 : /******************************************************************/
1034 : /*
1035 : PyCArrayType_Type
1036 : */
1037 : /*
1038 : PyCArrayType_new ensures that the new Array subclass created has a _length_
1039 : attribute, and a _type_ attribute.
1040 : */
1041 :
1042 : static int
1043 0 : CharArray_set_raw(CDataObject *self, PyObject *value)
1044 : {
1045 : char *ptr;
1046 : Py_ssize_t size;
1047 : Py_buffer view;
1048 :
1049 0 : if (PyObject_GetBuffer(value, &view, PyBUF_SIMPLE) < 0)
1050 0 : return -1;
1051 0 : size = view.len;
1052 0 : ptr = view.buf;
1053 0 : if (size > self->b_size) {
1054 0 : PyErr_SetString(PyExc_ValueError,
1055 : "string too long");
1056 0 : goto fail;
1057 : }
1058 :
1059 0 : memcpy(self->b_ptr, ptr, size);
1060 :
1061 0 : PyBuffer_Release(&view);
1062 0 : return 0;
1063 : fail:
1064 0 : PyBuffer_Release(&view);
1065 0 : return -1;
1066 : }
1067 :
1068 : static PyObject *
1069 0 : CharArray_get_raw(CDataObject *self)
1070 : {
1071 0 : return PyBytes_FromStringAndSize(self->b_ptr, self->b_size);
1072 : }
1073 :
1074 : static PyObject *
1075 0 : CharArray_get_value(CDataObject *self)
1076 : {
1077 : int i;
1078 0 : char *ptr = self->b_ptr;
1079 0 : for (i = 0; i < self->b_size; ++i)
1080 0 : if (*ptr++ == '\0')
1081 0 : break;
1082 0 : return PyBytes_FromStringAndSize(self->b_ptr, i);
1083 : }
1084 :
1085 : static int
1086 0 : CharArray_set_value(CDataObject *self, PyObject *value)
1087 : {
1088 : char *ptr;
1089 : Py_ssize_t size;
1090 :
1091 0 : if (value == NULL) {
1092 0 : PyErr_SetString(PyExc_TypeError,
1093 : "can't delete attribute");
1094 0 : return -1;
1095 : }
1096 :
1097 0 : if (!PyBytes_Check(value)) {
1098 0 : PyErr_Format(PyExc_TypeError,
1099 : "bytes expected instead of %s instance",
1100 0 : Py_TYPE(value)->tp_name);
1101 0 : return -1;
1102 : } else
1103 0 : Py_INCREF(value);
1104 0 : size = PyBytes_GET_SIZE(value);
1105 0 : if (size > self->b_size) {
1106 0 : PyErr_SetString(PyExc_ValueError,
1107 : "string too long");
1108 0 : Py_DECREF(value);
1109 0 : return -1;
1110 : }
1111 :
1112 0 : ptr = PyBytes_AS_STRING(value);
1113 0 : memcpy(self->b_ptr, ptr, size);
1114 0 : if (size < self->b_size)
1115 0 : self->b_ptr[size] = '\0';
1116 0 : Py_DECREF(value);
1117 :
1118 0 : return 0;
1119 : }
1120 :
1121 : static PyGetSetDef CharArray_getsets[] = {
1122 : { "raw", (getter)CharArray_get_raw, (setter)CharArray_set_raw,
1123 : "value", NULL },
1124 : { "value", (getter)CharArray_get_value, (setter)CharArray_set_value,
1125 : "string value"},
1126 : { NULL, NULL }
1127 : };
1128 :
1129 : #ifdef CTYPES_UNICODE
1130 : static PyObject *
1131 0 : WCharArray_get_value(CDataObject *self)
1132 : {
1133 : unsigned int i;
1134 0 : wchar_t *ptr = (wchar_t *)self->b_ptr;
1135 0 : for (i = 0; i < self->b_size/sizeof(wchar_t); ++i)
1136 0 : if (*ptr++ == (wchar_t)0)
1137 0 : break;
1138 0 : return PyUnicode_FromWideChar((wchar_t *)self->b_ptr, i);
1139 : }
1140 :
1141 : static int
1142 0 : WCharArray_set_value(CDataObject *self, PyObject *value)
1143 : {
1144 0 : Py_ssize_t result = 0;
1145 : Py_UNICODE *wstr;
1146 : Py_ssize_t len;
1147 :
1148 0 : if (value == NULL) {
1149 0 : PyErr_SetString(PyExc_TypeError,
1150 : "can't delete attribute");
1151 0 : return -1;
1152 : }
1153 0 : if (!PyUnicode_Check(value)) {
1154 0 : PyErr_Format(PyExc_TypeError,
1155 : "unicode string expected instead of %s instance",
1156 0 : Py_TYPE(value)->tp_name);
1157 0 : return -1;
1158 : } else
1159 0 : Py_INCREF(value);
1160 :
1161 0 : wstr = PyUnicode_AsUnicodeAndSize(value, &len);
1162 0 : if (wstr == NULL)
1163 0 : return -1;
1164 0 : if ((unsigned)len > self->b_size/sizeof(wchar_t)) {
1165 0 : PyErr_SetString(PyExc_ValueError,
1166 : "string too long");
1167 0 : result = -1;
1168 0 : goto done;
1169 : }
1170 0 : result = PyUnicode_AsWideChar(value,
1171 0 : (wchar_t *)self->b_ptr,
1172 0 : self->b_size/sizeof(wchar_t));
1173 0 : if (result >= 0 && (size_t)result < self->b_size/sizeof(wchar_t))
1174 0 : ((wchar_t *)self->b_ptr)[result] = (wchar_t)0;
1175 : done:
1176 0 : Py_DECREF(value);
1177 :
1178 0 : return result >= 0 ? 0 : -1;
1179 : }
1180 :
1181 : static PyGetSetDef WCharArray_getsets[] = {
1182 : { "value", (getter)WCharArray_get_value, (setter)WCharArray_set_value,
1183 : "string value"},
1184 : { NULL, NULL }
1185 : };
1186 : #endif
1187 :
1188 : /*
1189 : The next three functions copied from Python's typeobject.c.
1190 :
1191 : They are used to attach methods, members, or getsets to a type *after* it
1192 : has been created: Arrays of characters have additional getsets to treat them
1193 : as strings.
1194 : */
1195 : /*
1196 : static int
1197 : add_methods(PyTypeObject *type, PyMethodDef *meth)
1198 : {
1199 : PyObject *dict = type->tp_dict;
1200 : for (; meth->ml_name != NULL; meth++) {
1201 : PyObject *descr;
1202 : descr = PyDescr_NewMethod(type, meth);
1203 : if (descr == NULL)
1204 : return -1;
1205 : if (PyDict_SetItemString(dict,meth->ml_name, descr) < 0)
1206 : return -1;
1207 : Py_DECREF(descr);
1208 : }
1209 : return 0;
1210 : }
1211 :
1212 : static int
1213 : add_members(PyTypeObject *type, PyMemberDef *memb)
1214 : {
1215 : PyObject *dict = type->tp_dict;
1216 : for (; memb->name != NULL; memb++) {
1217 : PyObject *descr;
1218 : descr = PyDescr_NewMember(type, memb);
1219 : if (descr == NULL)
1220 : return -1;
1221 : if (PyDict_SetItemString(dict, memb->name, descr) < 0)
1222 : return -1;
1223 : Py_DECREF(descr);
1224 : }
1225 : return 0;
1226 : }
1227 : */
1228 :
1229 : static int
1230 0 : add_getset(PyTypeObject *type, PyGetSetDef *gsp)
1231 : {
1232 0 : PyObject *dict = type->tp_dict;
1233 0 : for (; gsp->name != NULL; gsp++) {
1234 : PyObject *descr;
1235 0 : descr = PyDescr_NewGetSet(type, gsp);
1236 0 : if (descr == NULL)
1237 0 : return -1;
1238 0 : if (PyDict_SetItemString(dict, gsp->name, descr) < 0)
1239 0 : return -1;
1240 0 : Py_DECREF(descr);
1241 : }
1242 0 : return 0;
1243 : }
1244 :
1245 : static PyCArgObject *
1246 0 : PyCArrayType_paramfunc(CDataObject *self)
1247 : {
1248 0 : PyCArgObject *p = PyCArgObject_new();
1249 0 : if (p == NULL)
1250 0 : return NULL;
1251 0 : p->tag = 'P';
1252 0 : p->pffi_type = &ffi_type_pointer;
1253 0 : p->value.p = (char *)self->b_ptr;
1254 0 : Py_INCREF(self);
1255 0 : p->obj = (PyObject *)self;
1256 0 : return p;
1257 : }
1258 :
1259 : static PyObject *
1260 0 : PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1261 : {
1262 : PyTypeObject *result;
1263 : StgDictObject *stgdict;
1264 : StgDictObject *itemdict;
1265 : PyObject *length_attr, *type_attr;
1266 : long length;
1267 : int overflow;
1268 : Py_ssize_t itemsize, itemalign;
1269 : char buf[32];
1270 :
1271 : /* create the new instance (which is a class,
1272 : since we are a metatype!) */
1273 0 : result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds);
1274 0 : if (result == NULL)
1275 0 : return NULL;
1276 :
1277 : /* Initialize these variables to NULL so that we can simplify error
1278 : handling by using Py_XDECREF. */
1279 0 : stgdict = NULL;
1280 0 : type_attr = NULL;
1281 :
1282 0 : length_attr = PyObject_GetAttrString((PyObject *)result, "_length_");
1283 0 : if (!length_attr || !PyLong_Check(length_attr)) {
1284 0 : PyErr_SetString(PyExc_AttributeError,
1285 : "class must define a '_length_' attribute, "
1286 : "which must be a positive integer");
1287 0 : Py_XDECREF(length_attr);
1288 0 : goto error;
1289 : }
1290 0 : length = PyLong_AsLongAndOverflow(length_attr, &overflow);
1291 0 : if (overflow) {
1292 0 : PyErr_SetString(PyExc_OverflowError,
1293 : "The '_length_' attribute is too large");
1294 0 : Py_DECREF(length_attr);
1295 0 : goto error;
1296 : }
1297 0 : Py_DECREF(length_attr);
1298 :
1299 0 : type_attr = PyObject_GetAttrString((PyObject *)result, "_type_");
1300 0 : if (!type_attr) {
1301 0 : PyErr_SetString(PyExc_AttributeError,
1302 : "class must define a '_type_' attribute");
1303 0 : goto error;
1304 : }
1305 :
1306 0 : stgdict = (StgDictObject *)PyObject_CallObject(
1307 : (PyObject *)&PyCStgDict_Type, NULL);
1308 0 : if (!stgdict)
1309 0 : goto error;
1310 :
1311 0 : itemdict = PyType_stgdict(type_attr);
1312 0 : if (!itemdict) {
1313 0 : PyErr_SetString(PyExc_TypeError,
1314 : "_type_ must have storage info");
1315 0 : goto error;
1316 : }
1317 :
1318 : assert(itemdict->format);
1319 0 : if (itemdict->format[0] == '(') {
1320 0 : sprintf(buf, "(%ld,", length);
1321 0 : stgdict->format = _ctypes_alloc_format_string(buf, itemdict->format+1);
1322 : } else {
1323 0 : sprintf(buf, "(%ld)", length);
1324 0 : stgdict->format = _ctypes_alloc_format_string(buf, itemdict->format);
1325 : }
1326 0 : if (stgdict->format == NULL)
1327 0 : goto error;
1328 0 : stgdict->ndim = itemdict->ndim + 1;
1329 0 : stgdict->shape = PyMem_Malloc(sizeof(Py_ssize_t *) * stgdict->ndim);
1330 0 : if (stgdict->shape == NULL)
1331 0 : goto error;
1332 0 : stgdict->shape[0] = length;
1333 0 : memmove(&stgdict->shape[1], itemdict->shape,
1334 0 : sizeof(Py_ssize_t) * (stgdict->ndim - 1));
1335 :
1336 0 : itemsize = itemdict->size;
1337 0 : if (length * itemsize < 0) {
1338 0 : PyErr_SetString(PyExc_OverflowError,
1339 : "array too large");
1340 0 : goto error;
1341 : }
1342 :
1343 0 : itemalign = itemdict->align;
1344 :
1345 0 : if (itemdict->flags & (TYPEFLAG_ISPOINTER | TYPEFLAG_HASPOINTER))
1346 0 : stgdict->flags |= TYPEFLAG_HASPOINTER;
1347 :
1348 0 : stgdict->size = itemsize * length;
1349 0 : stgdict->align = itemalign;
1350 0 : stgdict->length = length;
1351 0 : stgdict->proto = type_attr;
1352 :
1353 0 : stgdict->paramfunc = &PyCArrayType_paramfunc;
1354 :
1355 : /* Arrays are passed as pointers to function calls. */
1356 0 : stgdict->ffi_type_pointer = ffi_type_pointer;
1357 :
1358 : /* replace the class dict by our updated spam dict */
1359 0 : if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict))
1360 0 : goto error;
1361 0 : Py_DECREF(result->tp_dict);
1362 0 : result->tp_dict = (PyObject *)stgdict;
1363 :
1364 : /* Special case for character arrays.
1365 : A permanent annoyance: char arrays are also strings!
1366 : */
1367 0 : if (itemdict->getfunc == _ctypes_get_fielddesc("c")->getfunc) {
1368 0 : if (-1 == add_getset(result, CharArray_getsets))
1369 0 : goto error;
1370 : #ifdef CTYPES_UNICODE
1371 0 : } else if (itemdict->getfunc == _ctypes_get_fielddesc("u")->getfunc) {
1372 0 : if (-1 == add_getset(result, WCharArray_getsets))
1373 0 : goto error;
1374 : #endif
1375 : }
1376 :
1377 0 : return (PyObject *)result;
1378 : error:
1379 0 : Py_XDECREF((PyObject*)stgdict);
1380 0 : Py_XDECREF(type_attr);
1381 0 : Py_DECREF(result);
1382 0 : return NULL;
1383 : }
1384 :
1385 : PyTypeObject PyCArrayType_Type = {
1386 : PyVarObject_HEAD_INIT(NULL, 0)
1387 : "_ctypes.PyCArrayType", /* tp_name */
1388 : 0, /* tp_basicsize */
1389 : 0, /* tp_itemsize */
1390 : 0, /* tp_dealloc */
1391 : 0, /* tp_print */
1392 : 0, /* tp_getattr */
1393 : 0, /* tp_setattr */
1394 : 0, /* tp_reserved */
1395 : 0, /* tp_repr */
1396 : 0, /* tp_as_number */
1397 : &CDataType_as_sequence, /* tp_as_sequence */
1398 : 0, /* tp_as_mapping */
1399 : 0, /* tp_hash */
1400 : 0, /* tp_call */
1401 : 0, /* tp_str */
1402 : 0, /* tp_getattro */
1403 : 0, /* tp_setattro */
1404 : 0, /* tp_as_buffer */
1405 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
1406 : "metatype for the Array Objects", /* tp_doc */
1407 : 0, /* tp_traverse */
1408 : 0, /* tp_clear */
1409 : 0, /* tp_richcompare */
1410 : 0, /* tp_weaklistoffset */
1411 : 0, /* tp_iter */
1412 : 0, /* tp_iternext */
1413 : CDataType_methods, /* tp_methods */
1414 : 0, /* tp_members */
1415 : 0, /* tp_getset */
1416 : 0, /* tp_base */
1417 : 0, /* tp_dict */
1418 : 0, /* tp_descr_get */
1419 : 0, /* tp_descr_set */
1420 : 0, /* tp_dictoffset */
1421 : 0, /* tp_init */
1422 : 0, /* tp_alloc */
1423 : PyCArrayType_new, /* tp_new */
1424 : 0, /* tp_free */
1425 : };
1426 :
1427 :
1428 : /******************************************************************/
1429 : /*
1430 : PyCSimpleType_Type
1431 : */
1432 : /*
1433 :
1434 : PyCSimpleType_new ensures that the new Simple_Type subclass created has a valid
1435 : _type_ attribute.
1436 :
1437 : */
1438 :
1439 : static char *SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOv?g";
1440 :
1441 : static PyObject *
1442 0 : c_wchar_p_from_param(PyObject *type, PyObject *value)
1443 : {
1444 : PyObject *as_parameter;
1445 : int res;
1446 0 : if (value == Py_None) {
1447 0 : Py_INCREF(Py_None);
1448 0 : return Py_None;
1449 : }
1450 0 : if (PyUnicode_Check(value) || PyBytes_Check(value)) {
1451 : PyCArgObject *parg;
1452 0 : struct fielddesc *fd = _ctypes_get_fielddesc("Z");
1453 :
1454 0 : parg = PyCArgObject_new();
1455 0 : if (parg == NULL)
1456 0 : return NULL;
1457 0 : parg->pffi_type = &ffi_type_pointer;
1458 0 : parg->tag = 'Z';
1459 0 : parg->obj = fd->setfunc(&parg->value, value, 0);
1460 0 : if (parg->obj == NULL) {
1461 0 : Py_DECREF(parg);
1462 0 : return NULL;
1463 : }
1464 0 : return (PyObject *)parg;
1465 : }
1466 0 : res = PyObject_IsInstance(value, type);
1467 0 : if (res == -1)
1468 0 : return NULL;
1469 0 : if (res) {
1470 0 : Py_INCREF(value);
1471 0 : return value;
1472 : }
1473 0 : if (ArrayObject_Check(value) || PointerObject_Check(value)) {
1474 : /* c_wchar array instance or pointer(c_wchar(...)) */
1475 0 : StgDictObject *dt = PyObject_stgdict(value);
1476 : StgDictObject *dict;
1477 : assert(dt); /* Cannot be NULL for pointer or array objects */
1478 0 : dict = dt && dt->proto ? PyType_stgdict(dt->proto) : NULL;
1479 0 : if (dict && (dict->setfunc == _ctypes_get_fielddesc("u")->setfunc)) {
1480 0 : Py_INCREF(value);
1481 0 : return value;
1482 : }
1483 : }
1484 0 : if (PyCArg_CheckExact(value)) {
1485 : /* byref(c_char(...)) */
1486 0 : PyCArgObject *a = (PyCArgObject *)value;
1487 0 : StgDictObject *dict = PyObject_stgdict(a->obj);
1488 0 : if (dict && (dict->setfunc == _ctypes_get_fielddesc("u")->setfunc)) {
1489 0 : Py_INCREF(value);
1490 0 : return value;
1491 : }
1492 : }
1493 :
1494 0 : as_parameter = PyObject_GetAttrString(value, "_as_parameter_");
1495 0 : if (as_parameter) {
1496 0 : value = c_wchar_p_from_param(type, as_parameter);
1497 0 : Py_DECREF(as_parameter);
1498 0 : return value;
1499 : }
1500 : /* XXX better message */
1501 0 : PyErr_SetString(PyExc_TypeError,
1502 : "wrong type");
1503 0 : return NULL;
1504 : }
1505 :
1506 : static PyObject *
1507 0 : c_char_p_from_param(PyObject *type, PyObject *value)
1508 : {
1509 : PyObject *as_parameter;
1510 : int res;
1511 0 : if (value == Py_None) {
1512 0 : Py_INCREF(Py_None);
1513 0 : return Py_None;
1514 : }
1515 0 : if (PyBytes_Check(value)) {
1516 : PyCArgObject *parg;
1517 0 : struct fielddesc *fd = _ctypes_get_fielddesc("z");
1518 :
1519 0 : parg = PyCArgObject_new();
1520 0 : if (parg == NULL)
1521 0 : return NULL;
1522 0 : parg->pffi_type = &ffi_type_pointer;
1523 0 : parg->tag = 'z';
1524 0 : parg->obj = fd->setfunc(&parg->value, value, 0);
1525 0 : if (parg->obj == NULL) {
1526 0 : Py_DECREF(parg);
1527 0 : return NULL;
1528 : }
1529 0 : return (PyObject *)parg;
1530 : }
1531 0 : res = PyObject_IsInstance(value, type);
1532 0 : if (res == -1)
1533 0 : return NULL;
1534 0 : if (res) {
1535 0 : Py_INCREF(value);
1536 0 : return value;
1537 : }
1538 0 : if (ArrayObject_Check(value) || PointerObject_Check(value)) {
1539 : /* c_char array instance or pointer(c_char(...)) */
1540 0 : StgDictObject *dt = PyObject_stgdict(value);
1541 : StgDictObject *dict;
1542 : assert(dt); /* Cannot be NULL for pointer or array objects */
1543 0 : dict = dt && dt->proto ? PyType_stgdict(dt->proto) : NULL;
1544 0 : if (dict && (dict->setfunc == _ctypes_get_fielddesc("c")->setfunc)) {
1545 0 : Py_INCREF(value);
1546 0 : return value;
1547 : }
1548 : }
1549 0 : if (PyCArg_CheckExact(value)) {
1550 : /* byref(c_char(...)) */
1551 0 : PyCArgObject *a = (PyCArgObject *)value;
1552 0 : StgDictObject *dict = PyObject_stgdict(a->obj);
1553 0 : if (dict && (dict->setfunc == _ctypes_get_fielddesc("c")->setfunc)) {
1554 0 : Py_INCREF(value);
1555 0 : return value;
1556 : }
1557 : }
1558 :
1559 0 : as_parameter = PyObject_GetAttrString(value, "_as_parameter_");
1560 0 : if (as_parameter) {
1561 0 : value = c_char_p_from_param(type, as_parameter);
1562 0 : Py_DECREF(as_parameter);
1563 0 : return value;
1564 : }
1565 : /* XXX better message */
1566 0 : PyErr_SetString(PyExc_TypeError,
1567 : "wrong type");
1568 0 : return NULL;
1569 : }
1570 :
1571 : static PyObject *
1572 0 : c_void_p_from_param(PyObject *type, PyObject *value)
1573 : {
1574 : StgDictObject *stgd;
1575 : PyObject *as_parameter;
1576 : int res;
1577 :
1578 : /* None */
1579 0 : if (value == Py_None) {
1580 0 : Py_INCREF(Py_None);
1581 0 : return Py_None;
1582 : }
1583 : /* Should probably allow buffer interface as well */
1584 : /* int, long */
1585 0 : if (PyLong_Check(value)) {
1586 : PyCArgObject *parg;
1587 0 : struct fielddesc *fd = _ctypes_get_fielddesc("P");
1588 :
1589 0 : parg = PyCArgObject_new();
1590 0 : if (parg == NULL)
1591 0 : return NULL;
1592 0 : parg->pffi_type = &ffi_type_pointer;
1593 0 : parg->tag = 'P';
1594 0 : parg->obj = fd->setfunc(&parg->value, value, 0);
1595 0 : if (parg->obj == NULL) {
1596 0 : Py_DECREF(parg);
1597 0 : return NULL;
1598 : }
1599 0 : return (PyObject *)parg;
1600 : }
1601 : /* XXX struni: remove later */
1602 : /* string */
1603 0 : if (PyBytes_Check(value)) {
1604 : PyCArgObject *parg;
1605 0 : struct fielddesc *fd = _ctypes_get_fielddesc("z");
1606 :
1607 0 : parg = PyCArgObject_new();
1608 0 : if (parg == NULL)
1609 0 : return NULL;
1610 0 : parg->pffi_type = &ffi_type_pointer;
1611 0 : parg->tag = 'z';
1612 0 : parg->obj = fd->setfunc(&parg->value, value, 0);
1613 0 : if (parg->obj == NULL) {
1614 0 : Py_DECREF(parg);
1615 0 : return NULL;
1616 : }
1617 0 : return (PyObject *)parg;
1618 : }
1619 : /* bytes */
1620 0 : if (PyByteArray_Check(value)) {
1621 : PyCArgObject *parg;
1622 0 : struct fielddesc *fd = _ctypes_get_fielddesc("z");
1623 :
1624 0 : parg = PyCArgObject_new();
1625 0 : if (parg == NULL)
1626 0 : return NULL;
1627 0 : parg->pffi_type = &ffi_type_pointer;
1628 0 : parg->tag = 'z';
1629 0 : parg->obj = fd->setfunc(&parg->value, value, 0);
1630 0 : if (parg->obj == NULL) {
1631 0 : Py_DECREF(parg);
1632 0 : return NULL;
1633 : }
1634 0 : return (PyObject *)parg;
1635 : }
1636 : /* unicode */
1637 0 : if (PyUnicode_Check(value)) {
1638 : PyCArgObject *parg;
1639 0 : struct fielddesc *fd = _ctypes_get_fielddesc("Z");
1640 :
1641 0 : parg = PyCArgObject_new();
1642 0 : if (parg == NULL)
1643 0 : return NULL;
1644 0 : parg->pffi_type = &ffi_type_pointer;
1645 0 : parg->tag = 'Z';
1646 0 : parg->obj = fd->setfunc(&parg->value, value, 0);
1647 0 : if (parg->obj == NULL) {
1648 0 : Py_DECREF(parg);
1649 0 : return NULL;
1650 : }
1651 0 : return (PyObject *)parg;
1652 : }
1653 : /* c_void_p instance (or subclass) */
1654 0 : res = PyObject_IsInstance(value, type);
1655 0 : if (res == -1)
1656 0 : return NULL;
1657 0 : if (res) {
1658 : /* c_void_p instances */
1659 0 : Py_INCREF(value);
1660 0 : return value;
1661 : }
1662 : /* ctypes array or pointer instance */
1663 0 : if (ArrayObject_Check(value) || PointerObject_Check(value)) {
1664 : /* Any array or pointer is accepted */
1665 0 : Py_INCREF(value);
1666 0 : return value;
1667 : }
1668 : /* byref(...) */
1669 0 : if (PyCArg_CheckExact(value)) {
1670 : /* byref(c_xxx()) */
1671 0 : PyCArgObject *a = (PyCArgObject *)value;
1672 0 : if (a->tag == 'P') {
1673 0 : Py_INCREF(value);
1674 0 : return value;
1675 : }
1676 : }
1677 : /* function pointer */
1678 0 : if (PyCFuncPtrObject_Check(value)) {
1679 : PyCArgObject *parg;
1680 : PyCFuncPtrObject *func;
1681 0 : func = (PyCFuncPtrObject *)value;
1682 0 : parg = PyCArgObject_new();
1683 0 : if (parg == NULL)
1684 0 : return NULL;
1685 0 : parg->pffi_type = &ffi_type_pointer;
1686 0 : parg->tag = 'P';
1687 0 : Py_INCREF(value);
1688 0 : parg->value.p = *(void **)func->b_ptr;
1689 0 : parg->obj = value;
1690 0 : return (PyObject *)parg;
1691 : }
1692 : /* c_char_p, c_wchar_p */
1693 0 : stgd = PyObject_stgdict(value);
1694 0 : if (stgd && CDataObject_Check(value) && stgd->proto && PyUnicode_Check(stgd->proto)) {
1695 : PyCArgObject *parg;
1696 :
1697 0 : switch (_PyUnicode_AsString(stgd->proto)[0]) {
1698 : case 'z': /* c_char_p */
1699 : case 'Z': /* c_wchar_p */
1700 0 : parg = PyCArgObject_new();
1701 0 : if (parg == NULL)
1702 0 : return NULL;
1703 0 : parg->pffi_type = &ffi_type_pointer;
1704 0 : parg->tag = 'Z';
1705 0 : Py_INCREF(value);
1706 0 : parg->obj = value;
1707 : /* Remember: b_ptr points to where the pointer is stored! */
1708 0 : parg->value.p = *(void **)(((CDataObject *)value)->b_ptr);
1709 0 : return (PyObject *)parg;
1710 : }
1711 : }
1712 :
1713 0 : as_parameter = PyObject_GetAttrString(value, "_as_parameter_");
1714 0 : if (as_parameter) {
1715 0 : value = c_void_p_from_param(type, as_parameter);
1716 0 : Py_DECREF(as_parameter);
1717 0 : return value;
1718 : }
1719 : /* XXX better message */
1720 0 : PyErr_SetString(PyExc_TypeError,
1721 : "wrong type");
1722 0 : return NULL;
1723 : }
1724 :
1725 : static PyMethodDef c_void_p_method = { "from_param", c_void_p_from_param, METH_O };
1726 : static PyMethodDef c_char_p_method = { "from_param", c_char_p_from_param, METH_O };
1727 : static PyMethodDef c_wchar_p_method = { "from_param", c_wchar_p_from_param, METH_O };
1728 :
1729 0 : static PyObject *CreateSwappedType(PyTypeObject *type, PyObject *args, PyObject *kwds,
1730 : PyObject *proto, struct fielddesc *fmt)
1731 : {
1732 : PyTypeObject *result;
1733 : StgDictObject *stgdict;
1734 0 : PyObject *name = PyTuple_GET_ITEM(args, 0);
1735 : PyObject *newname;
1736 : PyObject *swapped_args;
1737 : static PyObject *suffix;
1738 : Py_ssize_t i;
1739 :
1740 0 : swapped_args = PyTuple_New(PyTuple_GET_SIZE(args));
1741 0 : if (!swapped_args)
1742 0 : return NULL;
1743 :
1744 0 : if (suffix == NULL)
1745 : #ifdef WORDS_BIGENDIAN
1746 : suffix = PyUnicode_InternFromString("_le");
1747 : #else
1748 0 : suffix = PyUnicode_InternFromString("_be");
1749 : #endif
1750 :
1751 0 : newname = PyUnicode_Concat(name, suffix);
1752 0 : if (newname == NULL) {
1753 0 : return NULL;
1754 : }
1755 :
1756 0 : PyTuple_SET_ITEM(swapped_args, 0, newname);
1757 0 : for (i=1; i<PyTuple_GET_SIZE(args); ++i) {
1758 0 : PyObject *v = PyTuple_GET_ITEM(args, i);
1759 0 : Py_INCREF(v);
1760 0 : PyTuple_SET_ITEM(swapped_args, i, v);
1761 : }
1762 :
1763 : /* create the new instance (which is a class,
1764 : since we are a metatype!) */
1765 0 : result = (PyTypeObject *)PyType_Type.tp_new(type, swapped_args, kwds);
1766 0 : Py_DECREF(swapped_args);
1767 0 : if (result == NULL)
1768 0 : return NULL;
1769 :
1770 0 : stgdict = (StgDictObject *)PyObject_CallObject(
1771 : (PyObject *)&PyCStgDict_Type, NULL);
1772 0 : if (!stgdict) /* XXX leaks result! */
1773 0 : return NULL;
1774 :
1775 0 : stgdict->ffi_type_pointer = *fmt->pffi_type;
1776 0 : stgdict->align = fmt->pffi_type->alignment;
1777 0 : stgdict->length = 0;
1778 0 : stgdict->size = fmt->pffi_type->size;
1779 0 : stgdict->setfunc = fmt->setfunc_swapped;
1780 0 : stgdict->getfunc = fmt->getfunc_swapped;
1781 :
1782 0 : Py_INCREF(proto);
1783 0 : stgdict->proto = proto;
1784 :
1785 : /* replace the class dict by our updated spam dict */
1786 0 : if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict)) {
1787 0 : Py_DECREF(result);
1788 0 : Py_DECREF((PyObject *)stgdict);
1789 0 : return NULL;
1790 : }
1791 0 : Py_DECREF(result->tp_dict);
1792 0 : result->tp_dict = (PyObject *)stgdict;
1793 :
1794 0 : return (PyObject *)result;
1795 : }
1796 :
1797 : static PyCArgObject *
1798 0 : PyCSimpleType_paramfunc(CDataObject *self)
1799 : {
1800 : StgDictObject *dict;
1801 : char *fmt;
1802 : PyCArgObject *parg;
1803 : struct fielddesc *fd;
1804 :
1805 0 : dict = PyObject_stgdict((PyObject *)self);
1806 : assert(dict); /* Cannot be NULL for CDataObject instances */
1807 0 : fmt = _PyUnicode_AsString(dict->proto);
1808 : assert(fmt);
1809 :
1810 0 : fd = _ctypes_get_fielddesc(fmt);
1811 : assert(fd);
1812 :
1813 0 : parg = PyCArgObject_new();
1814 0 : if (parg == NULL)
1815 0 : return NULL;
1816 :
1817 0 : parg->tag = fmt[0];
1818 0 : parg->pffi_type = fd->pffi_type;
1819 0 : Py_INCREF(self);
1820 0 : parg->obj = (PyObject *)self;
1821 0 : memcpy(&parg->value, self->b_ptr, self->b_size);
1822 0 : return parg;
1823 : }
1824 :
1825 : static PyObject *
1826 0 : PyCSimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1827 : {
1828 : PyTypeObject *result;
1829 : StgDictObject *stgdict;
1830 : PyObject *proto;
1831 : const char *proto_str;
1832 : Py_ssize_t proto_len;
1833 : PyMethodDef *ml;
1834 : struct fielddesc *fmt;
1835 :
1836 : /* create the new instance (which is a class,
1837 : since we are a metatype!) */
1838 0 : result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds);
1839 0 : if (result == NULL)
1840 0 : return NULL;
1841 :
1842 0 : proto = PyObject_GetAttrString((PyObject *)result, "_type_"); /* new ref */
1843 0 : if (!proto) {
1844 0 : PyErr_SetString(PyExc_AttributeError,
1845 : "class must define a '_type_' attribute");
1846 : error:
1847 0 : Py_XDECREF(proto);
1848 0 : Py_XDECREF(result);
1849 0 : return NULL;
1850 : }
1851 0 : if (PyUnicode_Check(proto)) {
1852 0 : proto_str = PyUnicode_AsUTF8AndSize(proto, &proto_len);
1853 0 : if (!proto_str)
1854 0 : goto error;
1855 : } else {
1856 0 : PyErr_SetString(PyExc_TypeError,
1857 : "class must define a '_type_' string attribute");
1858 0 : goto error;
1859 : }
1860 0 : if (proto_len != 1) {
1861 0 : PyErr_SetString(PyExc_ValueError,
1862 : "class must define a '_type_' attribute "
1863 : "which must be a string of length 1");
1864 0 : goto error;
1865 : }
1866 0 : if (!strchr(SIMPLE_TYPE_CHARS, *proto_str)) {
1867 0 : PyErr_Format(PyExc_AttributeError,
1868 : "class must define a '_type_' attribute which must be\n"
1869 : "a single character string containing one of '%s'.",
1870 : SIMPLE_TYPE_CHARS);
1871 0 : goto error;
1872 : }
1873 0 : fmt = _ctypes_get_fielddesc(proto_str);
1874 0 : if (fmt == NULL) {
1875 0 : PyErr_Format(PyExc_ValueError,
1876 : "_type_ '%s' not supported", proto_str);
1877 0 : goto error;
1878 : }
1879 :
1880 0 : stgdict = (StgDictObject *)PyObject_CallObject(
1881 : (PyObject *)&PyCStgDict_Type, NULL);
1882 0 : if (!stgdict)
1883 0 : goto error;
1884 :
1885 0 : stgdict->ffi_type_pointer = *fmt->pffi_type;
1886 0 : stgdict->align = fmt->pffi_type->alignment;
1887 0 : stgdict->length = 0;
1888 0 : stgdict->size = fmt->pffi_type->size;
1889 0 : stgdict->setfunc = fmt->setfunc;
1890 0 : stgdict->getfunc = fmt->getfunc;
1891 : #ifdef WORDS_BIGENDIAN
1892 : stgdict->format = _ctypes_alloc_format_string(">", proto_str);
1893 : #else
1894 0 : stgdict->format = _ctypes_alloc_format_string("<", proto_str);
1895 : #endif
1896 0 : if (stgdict->format == NULL) {
1897 0 : Py_DECREF(result);
1898 0 : Py_DECREF(proto);
1899 0 : Py_DECREF((PyObject *)stgdict);
1900 0 : return NULL;
1901 : }
1902 :
1903 0 : stgdict->paramfunc = PyCSimpleType_paramfunc;
1904 : /*
1905 : if (result->tp_base != &Simple_Type) {
1906 : stgdict->setfunc = NULL;
1907 : stgdict->getfunc = NULL;
1908 : }
1909 : */
1910 :
1911 : /* This consumes the refcount on proto which we have */
1912 0 : stgdict->proto = proto;
1913 :
1914 : /* replace the class dict by our updated spam dict */
1915 0 : if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict)) {
1916 0 : Py_DECREF(result);
1917 0 : Py_DECREF((PyObject *)stgdict);
1918 0 : return NULL;
1919 : }
1920 0 : Py_DECREF(result->tp_dict);
1921 0 : result->tp_dict = (PyObject *)stgdict;
1922 :
1923 : /* Install from_param class methods in ctypes base classes.
1924 : Overrides the PyCSimpleType_from_param generic method.
1925 : */
1926 0 : if (result->tp_base == &Simple_Type) {
1927 0 : switch (*proto_str) {
1928 : case 'z': /* c_char_p */
1929 0 : ml = &c_char_p_method;
1930 0 : stgdict->flags |= TYPEFLAG_ISPOINTER;
1931 0 : break;
1932 : case 'Z': /* c_wchar_p */
1933 0 : ml = &c_wchar_p_method;
1934 0 : stgdict->flags |= TYPEFLAG_ISPOINTER;
1935 0 : break;
1936 : case 'P': /* c_void_p */
1937 0 : ml = &c_void_p_method;
1938 0 : stgdict->flags |= TYPEFLAG_ISPOINTER;
1939 0 : break;
1940 : case 's':
1941 : case 'X':
1942 : case 'O':
1943 0 : ml = NULL;
1944 0 : stgdict->flags |= TYPEFLAG_ISPOINTER;
1945 0 : break;
1946 : default:
1947 0 : ml = NULL;
1948 0 : break;
1949 : }
1950 :
1951 0 : if (ml) {
1952 : PyObject *meth;
1953 : int x;
1954 0 : meth = PyDescr_NewClassMethod(result, ml);
1955 0 : if (!meth)
1956 0 : return NULL;
1957 0 : x = PyDict_SetItemString(result->tp_dict,
1958 : ml->ml_name,
1959 : meth);
1960 0 : Py_DECREF(meth);
1961 0 : if (x == -1) {
1962 0 : Py_DECREF(result);
1963 0 : return NULL;
1964 : }
1965 : }
1966 : }
1967 :
1968 0 : if (type == &PyCSimpleType_Type && fmt->setfunc_swapped && fmt->getfunc_swapped) {
1969 0 : PyObject *swapped = CreateSwappedType(type, args, kwds,
1970 : proto, fmt);
1971 : StgDictObject *sw_dict;
1972 0 : if (swapped == NULL) {
1973 0 : Py_DECREF(result);
1974 0 : return NULL;
1975 : }
1976 0 : sw_dict = PyType_stgdict(swapped);
1977 : #ifdef WORDS_BIGENDIAN
1978 : PyObject_SetAttrString((PyObject *)result, "__ctype_le__", swapped);
1979 : PyObject_SetAttrString((PyObject *)result, "__ctype_be__", (PyObject *)result);
1980 : PyObject_SetAttrString(swapped, "__ctype_be__", (PyObject *)result);
1981 : PyObject_SetAttrString(swapped, "__ctype_le__", swapped);
1982 : /* We are creating the type for the OTHER endian */
1983 : sw_dict->format = _ctypes_alloc_format_string("<", stgdict->format+1);
1984 : #else
1985 0 : PyObject_SetAttrString((PyObject *)result, "__ctype_be__", swapped);
1986 0 : PyObject_SetAttrString((PyObject *)result, "__ctype_le__", (PyObject *)result);
1987 0 : PyObject_SetAttrString(swapped, "__ctype_le__", (PyObject *)result);
1988 0 : PyObject_SetAttrString(swapped, "__ctype_be__", swapped);
1989 : /* We are creating the type for the OTHER endian */
1990 0 : sw_dict->format = _ctypes_alloc_format_string(">", stgdict->format+1);
1991 : #endif
1992 0 : Py_DECREF(swapped);
1993 0 : if (PyErr_Occurred()) {
1994 0 : Py_DECREF(result);
1995 0 : return NULL;
1996 : }
1997 : };
1998 :
1999 0 : return (PyObject *)result;
2000 : }
2001 :
2002 : /*
2003 : * This is a *class method*.
2004 : * Convert a parameter into something that ConvParam can handle.
2005 : */
2006 : static PyObject *
2007 0 : PyCSimpleType_from_param(PyObject *type, PyObject *value)
2008 : {
2009 : StgDictObject *dict;
2010 : char *fmt;
2011 : PyCArgObject *parg;
2012 : struct fielddesc *fd;
2013 : PyObject *as_parameter;
2014 : int res;
2015 :
2016 : /* If the value is already an instance of the requested type,
2017 : we can use it as is */
2018 0 : res = PyObject_IsInstance(value, type);
2019 0 : if (res == -1)
2020 0 : return NULL;
2021 0 : if (res) {
2022 0 : Py_INCREF(value);
2023 0 : return value;
2024 : }
2025 :
2026 0 : dict = PyType_stgdict(type);
2027 : assert(dict);
2028 :
2029 : /* I think we can rely on this being a one-character string */
2030 0 : fmt = _PyUnicode_AsString(dict->proto);
2031 : assert(fmt);
2032 :
2033 0 : fd = _ctypes_get_fielddesc(fmt);
2034 : assert(fd);
2035 :
2036 0 : parg = PyCArgObject_new();
2037 0 : if (parg == NULL)
2038 0 : return NULL;
2039 :
2040 0 : parg->tag = fmt[0];
2041 0 : parg->pffi_type = fd->pffi_type;
2042 0 : parg->obj = fd->setfunc(&parg->value, value, 0);
2043 0 : if (parg->obj)
2044 0 : return (PyObject *)parg;
2045 0 : PyErr_Clear();
2046 0 : Py_DECREF(parg);
2047 :
2048 0 : as_parameter = PyObject_GetAttrString(value, "_as_parameter_");
2049 0 : if (as_parameter) {
2050 0 : if (Py_EnterRecursiveCall("while processing _as_parameter_")) {
2051 0 : Py_DECREF(as_parameter);
2052 0 : return NULL;
2053 : }
2054 0 : value = PyCSimpleType_from_param(type, as_parameter);
2055 0 : Py_LeaveRecursiveCall();
2056 0 : Py_DECREF(as_parameter);
2057 0 : return value;
2058 : }
2059 0 : PyErr_SetString(PyExc_TypeError,
2060 : "wrong type");
2061 0 : return NULL;
2062 : }
2063 :
2064 : static PyMethodDef PyCSimpleType_methods[] = {
2065 : { "from_param", PyCSimpleType_from_param, METH_O, from_param_doc },
2066 : { "from_address", CDataType_from_address, METH_O, from_address_doc },
2067 : { "from_buffer", CDataType_from_buffer, METH_VARARGS, from_buffer_doc, },
2068 : { "from_buffer_copy", CDataType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, },
2069 : { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc},
2070 : { NULL, NULL },
2071 : };
2072 :
2073 : PyTypeObject PyCSimpleType_Type = {
2074 : PyVarObject_HEAD_INIT(NULL, 0)
2075 : "_ctypes.PyCSimpleType", /* tp_name */
2076 : 0, /* tp_basicsize */
2077 : 0, /* tp_itemsize */
2078 : 0, /* tp_dealloc */
2079 : 0, /* tp_print */
2080 : 0, /* tp_getattr */
2081 : 0, /* tp_setattr */
2082 : 0, /* tp_reserved */
2083 : 0, /* tp_repr */
2084 : 0, /* tp_as_number */
2085 : &CDataType_as_sequence, /* tp_as_sequence */
2086 : 0, /* tp_as_mapping */
2087 : 0, /* tp_hash */
2088 : 0, /* tp_call */
2089 : 0, /* tp_str */
2090 : 0, /* tp_getattro */
2091 : 0, /* tp_setattro */
2092 : 0, /* tp_as_buffer */
2093 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
2094 : "metatype for the PyCSimpleType Objects", /* tp_doc */
2095 : 0, /* tp_traverse */
2096 : 0, /* tp_clear */
2097 : 0, /* tp_richcompare */
2098 : 0, /* tp_weaklistoffset */
2099 : 0, /* tp_iter */
2100 : 0, /* tp_iternext */
2101 : PyCSimpleType_methods, /* tp_methods */
2102 : 0, /* tp_members */
2103 : 0, /* tp_getset */
2104 : 0, /* tp_base */
2105 : 0, /* tp_dict */
2106 : 0, /* tp_descr_get */
2107 : 0, /* tp_descr_set */
2108 : 0, /* tp_dictoffset */
2109 : 0, /* tp_init */
2110 : 0, /* tp_alloc */
2111 : PyCSimpleType_new, /* tp_new */
2112 : 0, /* tp_free */
2113 : };
2114 :
2115 : /******************************************************************/
2116 : /*
2117 : PyCFuncPtrType_Type
2118 : */
2119 :
2120 : static PyObject *
2121 0 : converters_from_argtypes(PyObject *ob)
2122 : {
2123 : PyObject *converters;
2124 : Py_ssize_t i;
2125 : Py_ssize_t nArgs;
2126 :
2127 0 : ob = PySequence_Tuple(ob); /* new reference */
2128 0 : if (!ob) {
2129 0 : PyErr_SetString(PyExc_TypeError,
2130 : "_argtypes_ must be a sequence of types");
2131 0 : return NULL;
2132 : }
2133 :
2134 0 : nArgs = PyTuple_GET_SIZE(ob);
2135 0 : converters = PyTuple_New(nArgs);
2136 0 : if (!converters)
2137 0 : return NULL;
2138 :
2139 : /* I have to check if this is correct. Using c_char, which has a size
2140 : of 1, will be assumed to be pushed as only one byte!
2141 : Aren't these promoted to integers by the C compiler and pushed as 4 bytes?
2142 : */
2143 :
2144 0 : for (i = 0; i < nArgs; ++i) {
2145 0 : PyObject *tp = PyTuple_GET_ITEM(ob, i);
2146 0 : PyObject *cnv = PyObject_GetAttrString(tp, "from_param");
2147 0 : if (!cnv)
2148 0 : goto argtypes_error_1;
2149 0 : PyTuple_SET_ITEM(converters, i, cnv);
2150 : }
2151 0 : Py_DECREF(ob);
2152 0 : return converters;
2153 :
2154 : argtypes_error_1:
2155 0 : Py_XDECREF(converters);
2156 0 : Py_DECREF(ob);
2157 0 : PyErr_Format(PyExc_TypeError,
2158 : "item %zd in _argtypes_ has no from_param method",
2159 : i+1);
2160 0 : return NULL;
2161 : }
2162 :
2163 : static int
2164 0 : make_funcptrtype_dict(StgDictObject *stgdict)
2165 : {
2166 : PyObject *ob;
2167 0 : PyObject *converters = NULL;
2168 :
2169 0 : stgdict->align = _ctypes_get_fielddesc("P")->pffi_type->alignment;
2170 0 : stgdict->length = 1;
2171 0 : stgdict->size = sizeof(void *);
2172 0 : stgdict->setfunc = NULL;
2173 0 : stgdict->getfunc = NULL;
2174 0 : stgdict->ffi_type_pointer = ffi_type_pointer;
2175 :
2176 0 : ob = PyDict_GetItemString((PyObject *)stgdict, "_flags_");
2177 0 : if (!ob || !PyLong_Check(ob)) {
2178 0 : PyErr_SetString(PyExc_TypeError,
2179 : "class must define _flags_ which must be an integer");
2180 0 : return -1;
2181 : }
2182 0 : stgdict->flags = PyLong_AS_LONG(ob) | TYPEFLAG_ISPOINTER;
2183 :
2184 : /* _argtypes_ is optional... */
2185 0 : ob = PyDict_GetItemString((PyObject *)stgdict, "_argtypes_");
2186 0 : if (ob) {
2187 0 : converters = converters_from_argtypes(ob);
2188 0 : if (!converters)
2189 0 : goto error;
2190 0 : Py_INCREF(ob);
2191 0 : stgdict->argtypes = ob;
2192 0 : stgdict->converters = converters;
2193 : }
2194 :
2195 0 : ob = PyDict_GetItemString((PyObject *)stgdict, "_restype_");
2196 0 : if (ob) {
2197 0 : if (ob != Py_None && !PyType_stgdict(ob) && !PyCallable_Check(ob)) {
2198 0 : PyErr_SetString(PyExc_TypeError,
2199 : "_restype_ must be a type, a callable, or None");
2200 0 : return -1;
2201 : }
2202 0 : Py_INCREF(ob);
2203 0 : stgdict->restype = ob;
2204 0 : stgdict->checker = PyObject_GetAttrString(ob, "_check_retval_");
2205 0 : if (stgdict->checker == NULL)
2206 0 : PyErr_Clear();
2207 : }
2208 : /* XXX later, maybe.
2209 : ob = PyDict_GetItemString((PyObject *)stgdict, "_errcheck_");
2210 : if (ob) {
2211 : if (!PyCallable_Check(ob)) {
2212 : PyErr_SetString(PyExc_TypeError,
2213 : "_errcheck_ must be callable");
2214 : return -1;
2215 : }
2216 : Py_INCREF(ob);
2217 : stgdict->errcheck = ob;
2218 : }
2219 : */
2220 0 : return 0;
2221 :
2222 : error:
2223 0 : Py_XDECREF(converters);
2224 0 : return -1;
2225 :
2226 : }
2227 :
2228 : static PyCArgObject *
2229 0 : PyCFuncPtrType_paramfunc(CDataObject *self)
2230 : {
2231 : PyCArgObject *parg;
2232 :
2233 0 : parg = PyCArgObject_new();
2234 0 : if (parg == NULL)
2235 0 : return NULL;
2236 :
2237 0 : parg->tag = 'P';
2238 0 : parg->pffi_type = &ffi_type_pointer;
2239 0 : Py_INCREF(self);
2240 0 : parg->obj = (PyObject *)self;
2241 0 : parg->value.p = *(void **)self->b_ptr;
2242 0 : return parg;
2243 : }
2244 :
2245 : static PyObject *
2246 0 : PyCFuncPtrType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2247 : {
2248 : PyTypeObject *result;
2249 : StgDictObject *stgdict;
2250 :
2251 0 : stgdict = (StgDictObject *)PyObject_CallObject(
2252 : (PyObject *)&PyCStgDict_Type, NULL);
2253 0 : if (!stgdict)
2254 0 : return NULL;
2255 :
2256 0 : stgdict->paramfunc = PyCFuncPtrType_paramfunc;
2257 : /* We do NOT expose the function signature in the format string. It
2258 : is impossible, generally, because the only requirement for the
2259 : argtypes items is that they have a .from_param method - we do not
2260 : know the types of the arguments (although, in practice, most
2261 : argtypes would be a ctypes type).
2262 : */
2263 0 : stgdict->format = _ctypes_alloc_format_string(NULL, "X{}");
2264 0 : stgdict->flags |= TYPEFLAG_ISPOINTER;
2265 :
2266 : /* create the new instance (which is a class,
2267 : since we are a metatype!) */
2268 0 : result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds);
2269 0 : if (result == NULL) {
2270 0 : Py_DECREF((PyObject *)stgdict);
2271 0 : return NULL;
2272 : }
2273 :
2274 : /* replace the class dict by our updated storage dict */
2275 0 : if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict)) {
2276 0 : Py_DECREF(result);
2277 0 : Py_DECREF((PyObject *)stgdict);
2278 0 : return NULL;
2279 : }
2280 0 : Py_DECREF(result->tp_dict);
2281 0 : result->tp_dict = (PyObject *)stgdict;
2282 :
2283 0 : if (-1 == make_funcptrtype_dict(stgdict)) {
2284 0 : Py_DECREF(result);
2285 0 : return NULL;
2286 : }
2287 :
2288 0 : return (PyObject *)result;
2289 : }
2290 :
2291 : PyTypeObject PyCFuncPtrType_Type = {
2292 : PyVarObject_HEAD_INIT(NULL, 0)
2293 : "_ctypes.PyCFuncPtrType", /* tp_name */
2294 : 0, /* tp_basicsize */
2295 : 0, /* tp_itemsize */
2296 : 0, /* tp_dealloc */
2297 : 0, /* tp_print */
2298 : 0, /* tp_getattr */
2299 : 0, /* tp_setattr */
2300 : 0, /* tp_reserved */
2301 : 0, /* tp_repr */
2302 : 0, /* tp_as_number */
2303 : &CDataType_as_sequence, /* tp_as_sequence */
2304 : 0, /* tp_as_mapping */
2305 : 0, /* tp_hash */
2306 : 0, /* tp_call */
2307 : 0, /* tp_str */
2308 : 0, /* tp_getattro */
2309 : 0, /* tp_setattro */
2310 : 0, /* tp_as_buffer */
2311 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
2312 : "metatype for C function pointers", /* tp_doc */
2313 : (traverseproc)CDataType_traverse, /* tp_traverse */
2314 : (inquiry)CDataType_clear, /* tp_clear */
2315 : 0, /* tp_richcompare */
2316 : 0, /* tp_weaklistoffset */
2317 : 0, /* tp_iter */
2318 : 0, /* tp_iternext */
2319 : CDataType_methods, /* tp_methods */
2320 : 0, /* tp_members */
2321 : 0, /* tp_getset */
2322 : 0, /* tp_base */
2323 : 0, /* tp_dict */
2324 : 0, /* tp_descr_get */
2325 : 0, /* tp_descr_set */
2326 : 0, /* tp_dictoffset */
2327 : 0, /* tp_init */
2328 : 0, /* tp_alloc */
2329 : PyCFuncPtrType_new, /* tp_new */
2330 : 0, /* tp_free */
2331 : };
2332 :
2333 :
2334 : /*****************************************************************
2335 : * Code to keep needed objects alive
2336 : */
2337 :
2338 : static CDataObject *
2339 0 : PyCData_GetContainer(CDataObject *self)
2340 : {
2341 0 : while (self->b_base)
2342 0 : self = self->b_base;
2343 0 : if (self->b_objects == NULL) {
2344 0 : if (self->b_length) {
2345 0 : self->b_objects = PyDict_New();
2346 : } else {
2347 0 : Py_INCREF(Py_None);
2348 0 : self->b_objects = Py_None;
2349 : }
2350 : }
2351 0 : return self;
2352 : }
2353 :
2354 : static PyObject *
2355 0 : GetKeepedObjects(CDataObject *target)
2356 : {
2357 0 : return PyCData_GetContainer(target)->b_objects;
2358 : }
2359 :
2360 : static PyObject *
2361 0 : unique_key(CDataObject *target, Py_ssize_t index)
2362 : {
2363 : char string[256];
2364 0 : char *cp = string;
2365 : size_t bytes_left;
2366 :
2367 : assert(sizeof(string) - 1 > sizeof(Py_ssize_t) * 2);
2368 0 : cp += sprintf(cp, "%x", Py_SAFE_DOWNCAST(index, Py_ssize_t, int));
2369 0 : while (target->b_base) {
2370 0 : bytes_left = sizeof(string) - (cp - string) - 1;
2371 : /* Hex format needs 2 characters per byte */
2372 0 : if (bytes_left < sizeof(Py_ssize_t) * 2) {
2373 0 : PyErr_SetString(PyExc_ValueError,
2374 : "ctypes object structure too deep");
2375 0 : return NULL;
2376 : }
2377 0 : cp += sprintf(cp, ":%x", Py_SAFE_DOWNCAST(target->b_index, Py_ssize_t, int));
2378 0 : target = target->b_base;
2379 : }
2380 0 : return PyUnicode_FromStringAndSize(string, cp-string);
2381 : }
2382 :
2383 : /*
2384 : * Keep a reference to 'keep' in the 'target', at index 'index'.
2385 : *
2386 : * If 'keep' is None, do nothing.
2387 : *
2388 : * Otherwise create a dictionary (if it does not yet exist) id the root
2389 : * objects 'b_objects' item, which will store the 'keep' object under a unique
2390 : * key.
2391 : *
2392 : * The unique_key helper travels the target's b_base pointer down to the root,
2393 : * building a string containing hex-formatted indexes found during traversal,
2394 : * separated by colons.
2395 : *
2396 : * The index tuple is used as a key into the root object's b_objects dict.
2397 : *
2398 : * Note: This function steals a refcount of the third argument, even if it
2399 : * fails!
2400 : */
2401 : static int
2402 0 : KeepRef(CDataObject *target, Py_ssize_t index, PyObject *keep)
2403 : {
2404 : int result;
2405 : CDataObject *ob;
2406 : PyObject *key;
2407 :
2408 : /* Optimization: no need to store None */
2409 0 : if (keep == Py_None) {
2410 0 : Py_DECREF(Py_None);
2411 0 : return 0;
2412 : }
2413 0 : ob = PyCData_GetContainer(target);
2414 0 : if (ob->b_objects == NULL || !PyDict_CheckExact(ob->b_objects)) {
2415 0 : Py_XDECREF(ob->b_objects);
2416 0 : ob->b_objects = keep; /* refcount consumed */
2417 0 : return 0;
2418 : }
2419 0 : key = unique_key(target, index);
2420 0 : if (key == NULL) {
2421 0 : Py_DECREF(keep);
2422 0 : return -1;
2423 : }
2424 0 : result = PyDict_SetItem(ob->b_objects, key, keep);
2425 0 : Py_DECREF(key);
2426 0 : Py_DECREF(keep);
2427 0 : return result;
2428 : }
2429 :
2430 : /******************************************************************/
2431 : /*
2432 : PyCData_Type
2433 : */
2434 : static int
2435 0 : PyCData_traverse(CDataObject *self, visitproc visit, void *arg)
2436 : {
2437 0 : Py_VISIT(self->b_objects);
2438 0 : Py_VISIT((PyObject *)self->b_base);
2439 0 : return 0;
2440 : }
2441 :
2442 : static int
2443 0 : PyCData_clear(CDataObject *self)
2444 : {
2445 0 : StgDictObject *dict = PyObject_stgdict((PyObject *)self);
2446 : assert(dict); /* Cannot be NULL for CDataObject instances */
2447 0 : Py_CLEAR(self->b_objects);
2448 0 : if ((self->b_needsfree)
2449 0 : && ((size_t)dict->size > sizeof(self->b_value)))
2450 0 : PyMem_Free(self->b_ptr);
2451 0 : self->b_ptr = NULL;
2452 0 : Py_CLEAR(self->b_base);
2453 0 : return 0;
2454 : }
2455 :
2456 : static void
2457 0 : PyCData_dealloc(PyObject *self)
2458 : {
2459 0 : PyCData_clear((CDataObject *)self);
2460 0 : Py_TYPE(self)->tp_free(self);
2461 0 : }
2462 :
2463 : static PyMemberDef PyCData_members[] = {
2464 : { "_b_base_", T_OBJECT,
2465 : offsetof(CDataObject, b_base), READONLY,
2466 : "the base object" },
2467 : { "_b_needsfree_", T_INT,
2468 : offsetof(CDataObject, b_needsfree), READONLY,
2469 : "whether the object owns the memory or not" },
2470 : { "_objects", T_OBJECT,
2471 : offsetof(CDataObject, b_objects), READONLY,
2472 : "internal objects tree (NEVER CHANGE THIS OBJECT!)"},
2473 : { NULL },
2474 : };
2475 :
2476 0 : static int PyCData_NewGetBuffer(PyObject *_self, Py_buffer *view, int flags)
2477 : {
2478 0 : CDataObject *self = (CDataObject *)_self;
2479 0 : StgDictObject *dict = PyObject_stgdict(_self);
2480 : Py_ssize_t i;
2481 :
2482 0 : if (view == NULL) return 0;
2483 :
2484 0 : view->buf = self->b_ptr;
2485 0 : view->obj = _self;
2486 0 : Py_INCREF(_self);
2487 0 : view->len = self->b_size;
2488 0 : view->readonly = 0;
2489 : /* use default format character if not set */
2490 0 : view->format = dict->format ? dict->format : "B";
2491 0 : view->ndim = dict->ndim;
2492 0 : view->shape = dict->shape;
2493 0 : view->itemsize = self->b_size;
2494 0 : if (view->itemsize) {
2495 0 : for (i = 0; i < view->ndim; ++i) {
2496 0 : view->itemsize /= dict->shape[i];
2497 : }
2498 : }
2499 0 : view->strides = NULL;
2500 0 : view->suboffsets = NULL;
2501 0 : view->internal = NULL;
2502 0 : return 0;
2503 : }
2504 :
2505 : static PyBufferProcs PyCData_as_buffer = {
2506 : PyCData_NewGetBuffer,
2507 : NULL,
2508 : };
2509 :
2510 : /*
2511 : * CData objects are mutable, so they cannot be hashable!
2512 : */
2513 : static Py_hash_t
2514 0 : PyCData_nohash(PyObject *self)
2515 : {
2516 0 : PyErr_SetString(PyExc_TypeError, "unhashable type");
2517 0 : return -1;
2518 : }
2519 :
2520 : static PyObject *
2521 0 : PyCData_reduce(PyObject *_self, PyObject *args)
2522 : {
2523 0 : CDataObject *self = (CDataObject *)_self;
2524 :
2525 0 : if (PyObject_stgdict(_self)->flags & (TYPEFLAG_ISPOINTER|TYPEFLAG_HASPOINTER)) {
2526 0 : PyErr_SetString(PyExc_ValueError,
2527 : "ctypes objects containing pointers cannot be pickled");
2528 0 : return NULL;
2529 : }
2530 0 : return Py_BuildValue("O(O(NN))",
2531 : _unpickle,
2532 : Py_TYPE(_self),
2533 : PyObject_GetAttrString(_self, "__dict__"),
2534 0 : PyBytes_FromStringAndSize(self->b_ptr, self->b_size));
2535 : }
2536 :
2537 : static PyObject *
2538 0 : PyCData_setstate(PyObject *_self, PyObject *args)
2539 : {
2540 : void *data;
2541 : Py_ssize_t len;
2542 : int res;
2543 : PyObject *dict, *mydict;
2544 0 : CDataObject *self = (CDataObject *)_self;
2545 0 : if (!PyArg_ParseTuple(args, "Os#", &dict, &data, &len))
2546 0 : return NULL;
2547 0 : if (len > self->b_size)
2548 0 : len = self->b_size;
2549 0 : memmove(self->b_ptr, data, len);
2550 0 : mydict = PyObject_GetAttrString(_self, "__dict__");
2551 0 : res = PyDict_Update(mydict, dict);
2552 0 : Py_DECREF(mydict);
2553 0 : if (res == -1)
2554 0 : return NULL;
2555 0 : Py_INCREF(Py_None);
2556 0 : return Py_None;
2557 : }
2558 :
2559 : /*
2560 : * default __ctypes_from_outparam__ method returns self.
2561 : */
2562 : static PyObject *
2563 0 : PyCData_from_outparam(PyObject *self, PyObject *args)
2564 : {
2565 0 : Py_INCREF(self);
2566 0 : return self;
2567 : }
2568 :
2569 : static PyMethodDef PyCData_methods[] = {
2570 : { "__ctypes_from_outparam__", PyCData_from_outparam, METH_NOARGS, },
2571 : { "__reduce__", PyCData_reduce, METH_NOARGS, },
2572 : { "__setstate__", PyCData_setstate, METH_VARARGS, },
2573 : { NULL, NULL },
2574 : };
2575 :
2576 : PyTypeObject PyCData_Type = {
2577 : PyVarObject_HEAD_INIT(NULL, 0)
2578 : "_ctypes._CData",
2579 : sizeof(CDataObject), /* tp_basicsize */
2580 : 0, /* tp_itemsize */
2581 : PyCData_dealloc, /* tp_dealloc */
2582 : 0, /* tp_print */
2583 : 0, /* tp_getattr */
2584 : 0, /* tp_setattr */
2585 : 0, /* tp_reserved */
2586 : 0, /* tp_repr */
2587 : 0, /* tp_as_number */
2588 : 0, /* tp_as_sequence */
2589 : 0, /* tp_as_mapping */
2590 : PyCData_nohash, /* tp_hash */
2591 : 0, /* tp_call */
2592 : 0, /* tp_str */
2593 : 0, /* tp_getattro */
2594 : 0, /* tp_setattro */
2595 : &PyCData_as_buffer, /* tp_as_buffer */
2596 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
2597 : "XXX to be provided", /* tp_doc */
2598 : (traverseproc)PyCData_traverse, /* tp_traverse */
2599 : (inquiry)PyCData_clear, /* tp_clear */
2600 : 0, /* tp_richcompare */
2601 : 0, /* tp_weaklistoffset */
2602 : 0, /* tp_iter */
2603 : 0, /* tp_iternext */
2604 : PyCData_methods, /* tp_methods */
2605 : PyCData_members, /* tp_members */
2606 : 0, /* tp_getset */
2607 : 0, /* tp_base */
2608 : 0, /* tp_dict */
2609 : 0, /* tp_descr_get */
2610 : 0, /* tp_descr_set */
2611 : 0, /* tp_dictoffset */
2612 : 0, /* tp_init */
2613 : 0, /* tp_alloc */
2614 : 0, /* tp_new */
2615 : 0, /* tp_free */
2616 : };
2617 :
2618 0 : static int PyCData_MallocBuffer(CDataObject *obj, StgDictObject *dict)
2619 : {
2620 0 : if ((size_t)dict->size <= sizeof(obj->b_value)) {
2621 : /* No need to call malloc, can use the default buffer */
2622 0 : obj->b_ptr = (char *)&obj->b_value;
2623 : /* The b_needsfree flag does not mean that we actually did
2624 : call PyMem_Malloc to allocate the memory block; instead it
2625 : means we are the *owner* of the memory and are responsible
2626 : for freeing resources associated with the memory. This is
2627 : also the reason that b_needsfree is exposed to Python.
2628 : */
2629 0 : obj->b_needsfree = 1;
2630 : } else {
2631 : /* In python 2.4, and ctypes 0.9.6, the malloc call took about
2632 : 33% of the creation time for c_int().
2633 : */
2634 0 : obj->b_ptr = (char *)PyMem_Malloc(dict->size);
2635 0 : if (obj->b_ptr == NULL) {
2636 0 : PyErr_NoMemory();
2637 0 : return -1;
2638 : }
2639 0 : obj->b_needsfree = 1;
2640 0 : memset(obj->b_ptr, 0, dict->size);
2641 : }
2642 0 : obj->b_size = dict->size;
2643 0 : return 0;
2644 : }
2645 :
2646 : PyObject *
2647 0 : PyCData_FromBaseObj(PyObject *type, PyObject *base, Py_ssize_t index, char *adr)
2648 : {
2649 : CDataObject *cmem;
2650 : StgDictObject *dict;
2651 :
2652 : assert(PyType_Check(type));
2653 0 : dict = PyType_stgdict(type);
2654 0 : if (!dict) {
2655 0 : PyErr_SetString(PyExc_TypeError,
2656 : "abstract class");
2657 0 : return NULL;
2658 : }
2659 0 : dict->flags |= DICTFLAG_FINAL;
2660 0 : cmem = (CDataObject *)((PyTypeObject *)type)->tp_alloc((PyTypeObject *)type, 0);
2661 0 : if (cmem == NULL)
2662 0 : return NULL;
2663 : assert(CDataObject_Check(cmem));
2664 :
2665 0 : cmem->b_length = dict->length;
2666 0 : cmem->b_size = dict->size;
2667 0 : if (base) { /* use base's buffer */
2668 : assert(CDataObject_Check(base));
2669 0 : cmem->b_ptr = adr;
2670 0 : cmem->b_needsfree = 0;
2671 0 : Py_INCREF(base);
2672 0 : cmem->b_base = (CDataObject *)base;
2673 0 : cmem->b_index = index;
2674 : } else { /* copy contents of adr */
2675 0 : if (-1 == PyCData_MallocBuffer(cmem, dict)) {
2676 0 : return NULL;
2677 : Py_DECREF(cmem);
2678 : }
2679 0 : memcpy(cmem->b_ptr, adr, dict->size);
2680 0 : cmem->b_index = index;
2681 : }
2682 0 : return (PyObject *)cmem;
2683 : }
2684 :
2685 : /*
2686 : Box a memory block into a CData instance.
2687 : */
2688 : PyObject *
2689 0 : PyCData_AtAddress(PyObject *type, void *buf)
2690 : {
2691 : CDataObject *pd;
2692 : StgDictObject *dict;
2693 :
2694 : assert(PyType_Check(type));
2695 0 : dict = PyType_stgdict(type);
2696 0 : if (!dict) {
2697 0 : PyErr_SetString(PyExc_TypeError,
2698 : "abstract class");
2699 0 : return NULL;
2700 : }
2701 0 : dict->flags |= DICTFLAG_FINAL;
2702 :
2703 0 : pd = (CDataObject *)((PyTypeObject *)type)->tp_alloc((PyTypeObject *)type, 0);
2704 0 : if (!pd)
2705 0 : return NULL;
2706 : assert(CDataObject_Check(pd));
2707 0 : pd->b_ptr = (char *)buf;
2708 0 : pd->b_length = dict->length;
2709 0 : pd->b_size = dict->size;
2710 0 : return (PyObject *)pd;
2711 : }
2712 :
2713 : /*
2714 : This function returns TRUE for c_int, c_void_p, and these kind of
2715 : classes. FALSE otherwise FALSE also for subclasses of c_int and
2716 : such.
2717 : */
2718 0 : int _ctypes_simple_instance(PyObject *obj)
2719 : {
2720 0 : PyTypeObject *type = (PyTypeObject *)obj;
2721 :
2722 0 : if (PyCSimpleTypeObject_Check(type))
2723 0 : return type->tp_base != &Simple_Type;
2724 0 : return 0;
2725 : }
2726 :
2727 : PyObject *
2728 0 : PyCData_get(PyObject *type, GETFUNC getfunc, PyObject *src,
2729 : Py_ssize_t index, Py_ssize_t size, char *adr)
2730 : {
2731 : StgDictObject *dict;
2732 0 : if (getfunc)
2733 0 : return getfunc(adr, size);
2734 : assert(type);
2735 0 : dict = PyType_stgdict(type);
2736 0 : if (dict && dict->getfunc && !_ctypes_simple_instance(type))
2737 0 : return dict->getfunc(adr, size);
2738 0 : return PyCData_FromBaseObj(type, src, index, adr);
2739 : }
2740 :
2741 : /*
2742 : Helper function for PyCData_set below.
2743 : */
2744 : static PyObject *
2745 0 : _PyCData_set(CDataObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value,
2746 : Py_ssize_t size, char *ptr)
2747 : {
2748 : CDataObject *src;
2749 : int err;
2750 :
2751 0 : if (setfunc)
2752 0 : return setfunc(ptr, value, size);
2753 :
2754 0 : if (!CDataObject_Check(value)) {
2755 0 : StgDictObject *dict = PyType_stgdict(type);
2756 0 : if (dict && dict->setfunc)
2757 0 : return dict->setfunc(ptr, value, size);
2758 : /*
2759 : If value is a tuple, we try to call the type with the tuple
2760 : and use the result!
2761 : */
2762 : assert(PyType_Check(type));
2763 0 : if (PyTuple_Check(value)) {
2764 : PyObject *ob;
2765 : PyObject *result;
2766 0 : ob = PyObject_CallObject(type, value);
2767 0 : if (ob == NULL) {
2768 0 : _ctypes_extend_error(PyExc_RuntimeError, "(%s) ",
2769 : ((PyTypeObject *)type)->tp_name);
2770 0 : return NULL;
2771 : }
2772 0 : result = _PyCData_set(dst, type, setfunc, ob,
2773 : size, ptr);
2774 0 : Py_DECREF(ob);
2775 0 : return result;
2776 0 : } else if (value == Py_None && PyCPointerTypeObject_Check(type)) {
2777 0 : *(void **)ptr = NULL;
2778 0 : Py_INCREF(Py_None);
2779 0 : return Py_None;
2780 : } else {
2781 0 : PyErr_Format(PyExc_TypeError,
2782 : "expected %s instance, got %s",
2783 : ((PyTypeObject *)type)->tp_name,
2784 0 : Py_TYPE(value)->tp_name);
2785 0 : return NULL;
2786 : }
2787 : }
2788 0 : src = (CDataObject *)value;
2789 :
2790 0 : err = PyObject_IsInstance(value, type);
2791 0 : if (err == -1)
2792 0 : return NULL;
2793 0 : if (err) {
2794 0 : memcpy(ptr,
2795 0 : src->b_ptr,
2796 : size);
2797 :
2798 0 : if (PyCPointerTypeObject_Check(type))
2799 : /* XXX */;
2800 :
2801 0 : value = GetKeepedObjects(src);
2802 0 : Py_INCREF(value);
2803 0 : return value;
2804 : }
2805 :
2806 0 : if (PyCPointerTypeObject_Check(type)
2807 0 : && ArrayObject_Check(value)) {
2808 : StgDictObject *p1, *p2;
2809 : PyObject *keep;
2810 0 : p1 = PyObject_stgdict(value);
2811 : assert(p1); /* Cannot be NULL for array instances */
2812 0 : p2 = PyType_stgdict(type);
2813 : assert(p2); /* Cannot be NULL for pointer types */
2814 :
2815 0 : if (p1->proto != p2->proto) {
2816 0 : PyErr_Format(PyExc_TypeError,
2817 : "incompatible types, %s instance instead of %s instance",
2818 0 : Py_TYPE(value)->tp_name,
2819 : ((PyTypeObject *)type)->tp_name);
2820 0 : return NULL;
2821 : }
2822 0 : *(void **)ptr = src->b_ptr;
2823 :
2824 0 : keep = GetKeepedObjects(src);
2825 : /*
2826 : We are assigning an array object to a field which represents
2827 : a pointer. This has the same effect as converting an array
2828 : into a pointer. So, again, we have to keep the whole object
2829 : pointed to (which is the array in this case) alive, and not
2830 : only it's object list. So we create a tuple, containing
2831 : b_objects list PLUS the array itself, and return that!
2832 : */
2833 0 : return PyTuple_Pack(2, keep, value);
2834 : }
2835 0 : PyErr_Format(PyExc_TypeError,
2836 : "incompatible types, %s instance instead of %s instance",
2837 0 : Py_TYPE(value)->tp_name,
2838 : ((PyTypeObject *)type)->tp_name);
2839 0 : return NULL;
2840 : }
2841 :
2842 : /*
2843 : * Set a slice in object 'dst', which has the type 'type',
2844 : * to the value 'value'.
2845 : */
2846 : int
2847 0 : PyCData_set(PyObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value,
2848 : Py_ssize_t index, Py_ssize_t size, char *ptr)
2849 : {
2850 0 : CDataObject *mem = (CDataObject *)dst;
2851 : PyObject *result;
2852 :
2853 0 : if (!CDataObject_Check(dst)) {
2854 0 : PyErr_SetString(PyExc_TypeError,
2855 : "not a ctype instance");
2856 0 : return -1;
2857 : }
2858 :
2859 0 : result = _PyCData_set(mem, type, setfunc, value,
2860 : size, ptr);
2861 0 : if (result == NULL)
2862 0 : return -1;
2863 :
2864 : /* KeepRef steals a refcount from it's last argument */
2865 : /* If KeepRef fails, we are stumped. The dst memory block has already
2866 : been changed */
2867 0 : return KeepRef(mem, index, result);
2868 : }
2869 :
2870 :
2871 : /******************************************************************/
2872 : static PyObject *
2873 0 : GenericPyCData_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2874 : {
2875 : CDataObject *obj;
2876 : StgDictObject *dict;
2877 :
2878 0 : dict = PyType_stgdict((PyObject *)type);
2879 0 : if (!dict) {
2880 0 : PyErr_SetString(PyExc_TypeError,
2881 : "abstract class");
2882 0 : return NULL;
2883 : }
2884 0 : dict->flags |= DICTFLAG_FINAL;
2885 :
2886 0 : obj = (CDataObject *)type->tp_alloc(type, 0);
2887 0 : if (!obj)
2888 0 : return NULL;
2889 :
2890 0 : obj->b_base = NULL;
2891 0 : obj->b_index = 0;
2892 0 : obj->b_objects = NULL;
2893 0 : obj->b_length = dict->length;
2894 :
2895 0 : if (-1 == PyCData_MallocBuffer(obj, dict)) {
2896 0 : Py_DECREF(obj);
2897 0 : return NULL;
2898 : }
2899 0 : return (PyObject *)obj;
2900 : }
2901 : /*****************************************************************/
2902 : /*
2903 : PyCFuncPtr_Type
2904 : */
2905 :
2906 : static int
2907 0 : PyCFuncPtr_set_errcheck(PyCFuncPtrObject *self, PyObject *ob)
2908 : {
2909 0 : if (ob && !PyCallable_Check(ob)) {
2910 0 : PyErr_SetString(PyExc_TypeError,
2911 : "the errcheck attribute must be callable");
2912 0 : return -1;
2913 : }
2914 0 : Py_XDECREF(self->errcheck);
2915 0 : Py_XINCREF(ob);
2916 0 : self->errcheck = ob;
2917 0 : return 0;
2918 : }
2919 :
2920 : static PyObject *
2921 0 : PyCFuncPtr_get_errcheck(PyCFuncPtrObject *self)
2922 : {
2923 0 : if (self->errcheck) {
2924 0 : Py_INCREF(self->errcheck);
2925 0 : return self->errcheck;
2926 : }
2927 0 : Py_INCREF(Py_None);
2928 0 : return Py_None;
2929 : }
2930 :
2931 : static int
2932 0 : PyCFuncPtr_set_restype(PyCFuncPtrObject *self, PyObject *ob)
2933 : {
2934 0 : if (ob == NULL) {
2935 0 : Py_XDECREF(self->restype);
2936 0 : self->restype = NULL;
2937 0 : Py_XDECREF(self->checker);
2938 0 : self->checker = NULL;
2939 0 : return 0;
2940 : }
2941 0 : if (ob != Py_None && !PyType_stgdict(ob) && !PyCallable_Check(ob)) {
2942 0 : PyErr_SetString(PyExc_TypeError,
2943 : "restype must be a type, a callable, or None");
2944 0 : return -1;
2945 : }
2946 0 : Py_XDECREF(self->checker);
2947 0 : Py_XDECREF(self->restype);
2948 0 : Py_INCREF(ob);
2949 0 : self->restype = ob;
2950 0 : self->checker = PyObject_GetAttrString(ob, "_check_retval_");
2951 0 : if (self->checker == NULL)
2952 0 : PyErr_Clear();
2953 0 : return 0;
2954 : }
2955 :
2956 : static PyObject *
2957 0 : PyCFuncPtr_get_restype(PyCFuncPtrObject *self)
2958 : {
2959 : StgDictObject *dict;
2960 0 : if (self->restype) {
2961 0 : Py_INCREF(self->restype);
2962 0 : return self->restype;
2963 : }
2964 0 : dict = PyObject_stgdict((PyObject *)self);
2965 : assert(dict); /* Cannot be NULL for PyCFuncPtrObject instances */
2966 0 : if (dict->restype) {
2967 0 : Py_INCREF(dict->restype);
2968 0 : return dict->restype;
2969 : } else {
2970 0 : Py_INCREF(Py_None);
2971 0 : return Py_None;
2972 : }
2973 : }
2974 :
2975 : static int
2976 0 : PyCFuncPtr_set_argtypes(PyCFuncPtrObject *self, PyObject *ob)
2977 : {
2978 : PyObject *converters;
2979 :
2980 0 : if (ob == NULL || ob == Py_None) {
2981 0 : Py_XDECREF(self->converters);
2982 0 : self->converters = NULL;
2983 0 : Py_XDECREF(self->argtypes);
2984 0 : self->argtypes = NULL;
2985 : } else {
2986 0 : converters = converters_from_argtypes(ob);
2987 0 : if (!converters)
2988 0 : return -1;
2989 0 : Py_XDECREF(self->converters);
2990 0 : self->converters = converters;
2991 0 : Py_XDECREF(self->argtypes);
2992 0 : Py_INCREF(ob);
2993 0 : self->argtypes = ob;
2994 : }
2995 0 : return 0;
2996 : }
2997 :
2998 : static PyObject *
2999 0 : PyCFuncPtr_get_argtypes(PyCFuncPtrObject *self)
3000 : {
3001 : StgDictObject *dict;
3002 0 : if (self->argtypes) {
3003 0 : Py_INCREF(self->argtypes);
3004 0 : return self->argtypes;
3005 : }
3006 0 : dict = PyObject_stgdict((PyObject *)self);
3007 : assert(dict); /* Cannot be NULL for PyCFuncPtrObject instances */
3008 0 : if (dict->argtypes) {
3009 0 : Py_INCREF(dict->argtypes);
3010 0 : return dict->argtypes;
3011 : } else {
3012 0 : Py_INCREF(Py_None);
3013 0 : return Py_None;
3014 : }
3015 : }
3016 :
3017 : static PyGetSetDef PyCFuncPtr_getsets[] = {
3018 : { "errcheck", (getter)PyCFuncPtr_get_errcheck, (setter)PyCFuncPtr_set_errcheck,
3019 : "a function to check for errors", NULL },
3020 : { "restype", (getter)PyCFuncPtr_get_restype, (setter)PyCFuncPtr_set_restype,
3021 : "specify the result type", NULL },
3022 : { "argtypes", (getter)PyCFuncPtr_get_argtypes,
3023 : (setter)PyCFuncPtr_set_argtypes,
3024 : "specify the argument types", NULL },
3025 : { NULL, NULL }
3026 : };
3027 :
3028 : #ifdef MS_WIN32
3029 : static PPROC FindAddress(void *handle, char *name, PyObject *type)
3030 : {
3031 : #ifdef MS_WIN64
3032 : /* win64 has no stdcall calling conv, so it should
3033 : also not have the name mangling of it.
3034 : */
3035 : return (PPROC)GetProcAddress(handle, name);
3036 : #else
3037 : PPROC address;
3038 : char *mangled_name;
3039 : int i;
3040 : StgDictObject *dict;
3041 :
3042 : address = (PPROC)GetProcAddress(handle, name);
3043 : if (address)
3044 : return address;
3045 : if (((size_t)name & ~0xFFFF) == 0) {
3046 : return NULL;
3047 : }
3048 :
3049 : dict = PyType_stgdict((PyObject *)type);
3050 : /* It should not happen that dict is NULL, but better be safe */
3051 : if (dict==NULL || dict->flags & FUNCFLAG_CDECL)
3052 : return address;
3053 :
3054 : /* for stdcall, try mangled names:
3055 : funcname -> _funcname@<n>
3056 : where n is 0, 4, 8, 12, ..., 128
3057 : */
3058 : mangled_name = alloca(strlen(name) + 1 + 1 + 1 + 3); /* \0 _ @ %d */
3059 : if (!mangled_name)
3060 : return NULL;
3061 : for (i = 0; i < 32; ++i) {
3062 : sprintf(mangled_name, "_%s@%d", name, i*4);
3063 : address = (PPROC)GetProcAddress(handle, mangled_name);
3064 : if (address)
3065 : return address;
3066 : }
3067 : return NULL;
3068 : #endif
3069 : }
3070 : #endif
3071 :
3072 : /* Return 1 if usable, 0 else and exception set. */
3073 : static int
3074 0 : _check_outarg_type(PyObject *arg, Py_ssize_t index)
3075 : {
3076 : StgDictObject *dict;
3077 :
3078 0 : if (PyCPointerTypeObject_Check(arg))
3079 0 : return 1;
3080 :
3081 0 : if (PyCArrayTypeObject_Check(arg))
3082 0 : return 1;
3083 :
3084 0 : dict = PyType_stgdict(arg);
3085 0 : if (dict
3086 : /* simple pointer types, c_void_p, c_wchar_p, BSTR, ... */
3087 0 : && PyUnicode_Check(dict->proto)
3088 : /* We only allow c_void_p, c_char_p and c_wchar_p as a simple output parameter type */
3089 0 : && (strchr("PzZ", _PyUnicode_AsString(dict->proto)[0]))) {
3090 0 : return 1;
3091 : }
3092 :
3093 0 : PyErr_Format(PyExc_TypeError,
3094 : "'out' parameter %d must be a pointer type, not %s",
3095 : Py_SAFE_DOWNCAST(index, Py_ssize_t, int),
3096 0 : PyType_Check(arg) ?
3097 : ((PyTypeObject *)arg)->tp_name :
3098 0 : Py_TYPE(arg)->tp_name);
3099 0 : return 0;
3100 : }
3101 :
3102 : /* Returns 1 on success, 0 on error */
3103 : static int
3104 0 : _validate_paramflags(PyTypeObject *type, PyObject *paramflags)
3105 : {
3106 : Py_ssize_t i, len;
3107 : StgDictObject *dict;
3108 : PyObject *argtypes;
3109 :
3110 0 : dict = PyType_stgdict((PyObject *)type);
3111 : assert(dict); /* Cannot be NULL. 'type' is a PyCFuncPtr type. */
3112 0 : argtypes = dict->argtypes;
3113 :
3114 0 : if (paramflags == NULL || dict->argtypes == NULL)
3115 0 : return 1;
3116 :
3117 0 : if (!PyTuple_Check(paramflags)) {
3118 0 : PyErr_SetString(PyExc_TypeError,
3119 : "paramflags must be a tuple or None");
3120 0 : return 0;
3121 : }
3122 :
3123 0 : len = PyTuple_GET_SIZE(paramflags);
3124 0 : if (len != PyTuple_GET_SIZE(dict->argtypes)) {
3125 0 : PyErr_SetString(PyExc_ValueError,
3126 : "paramflags must have the same length as argtypes");
3127 0 : return 0;
3128 : }
3129 :
3130 0 : for (i = 0; i < len; ++i) {
3131 0 : PyObject *item = PyTuple_GET_ITEM(paramflags, i);
3132 : int flag;
3133 : char *name;
3134 : PyObject *defval;
3135 : PyObject *typ;
3136 0 : if (!PyArg_ParseTuple(item, "i|ZO", &flag, &name, &defval)) {
3137 0 : PyErr_SetString(PyExc_TypeError,
3138 : "paramflags must be a sequence of (int [,string [,value]]) tuples");
3139 0 : return 0;
3140 : }
3141 0 : typ = PyTuple_GET_ITEM(argtypes, i);
3142 0 : switch (flag & (PARAMFLAG_FIN | PARAMFLAG_FOUT | PARAMFLAG_FLCID)) {
3143 : case 0:
3144 : case PARAMFLAG_FIN:
3145 : case PARAMFLAG_FIN | PARAMFLAG_FLCID:
3146 : case PARAMFLAG_FIN | PARAMFLAG_FOUT:
3147 0 : break;
3148 : case PARAMFLAG_FOUT:
3149 0 : if (!_check_outarg_type(typ, i+1))
3150 0 : return 0;
3151 0 : break;
3152 : default:
3153 0 : PyErr_Format(PyExc_TypeError,
3154 : "paramflag value %d not supported",
3155 : flag);
3156 0 : return 0;
3157 : }
3158 : }
3159 0 : return 1;
3160 : }
3161 :
3162 : static int
3163 0 : _get_name(PyObject *obj, char **pname)
3164 : {
3165 : #ifdef MS_WIN32
3166 : if (PyLong_Check(obj)) {
3167 : /* We have to use MAKEINTRESOURCEA for Windows CE.
3168 : Works on Windows as well, of course.
3169 : */
3170 : *pname = MAKEINTRESOURCEA(PyLong_AsUnsignedLongMask(obj) & 0xFFFF);
3171 : return 1;
3172 : }
3173 : #endif
3174 0 : if (PyBytes_Check(obj)) {
3175 0 : *pname = PyBytes_AS_STRING(obj);
3176 0 : return *pname ? 1 : 0;
3177 : }
3178 0 : if (PyUnicode_Check(obj)) {
3179 0 : *pname = _PyUnicode_AsString(obj);
3180 0 : return *pname ? 1 : 0;
3181 : }
3182 0 : PyErr_SetString(PyExc_TypeError,
3183 : "function name must be string or integer");
3184 0 : return 0;
3185 : }
3186 :
3187 :
3188 : static PyObject *
3189 0 : PyCFuncPtr_FromDll(PyTypeObject *type, PyObject *args, PyObject *kwds)
3190 : {
3191 : char *name;
3192 : int (* address)(void);
3193 : PyObject *dll;
3194 : PyObject *obj;
3195 : PyCFuncPtrObject *self;
3196 : void *handle;
3197 0 : PyObject *paramflags = NULL;
3198 :
3199 0 : if (!PyArg_ParseTuple(args, "(O&O)|O", _get_name, &name, &dll, ¶mflags))
3200 0 : return NULL;
3201 0 : if (paramflags == Py_None)
3202 0 : paramflags = NULL;
3203 :
3204 0 : obj = PyObject_GetAttrString(dll, "_handle");
3205 0 : if (!obj)
3206 0 : return NULL;
3207 0 : if (!PyLong_Check(obj)) {
3208 0 : PyErr_SetString(PyExc_TypeError,
3209 : "the _handle attribute of the second argument must be an integer");
3210 0 : Py_DECREF(obj);
3211 0 : return NULL;
3212 : }
3213 0 : handle = (void *)PyLong_AsVoidPtr(obj);
3214 0 : Py_DECREF(obj);
3215 0 : if (PyErr_Occurred()) {
3216 0 : PyErr_SetString(PyExc_ValueError,
3217 : "could not convert the _handle attribute to a pointer");
3218 0 : return NULL;
3219 : }
3220 :
3221 : #ifdef MS_WIN32
3222 : address = FindAddress(handle, name, (PyObject *)type);
3223 : if (!address) {
3224 : if (!IS_INTRESOURCE(name))
3225 : PyErr_Format(PyExc_AttributeError,
3226 : "function '%s' not found",
3227 : name);
3228 : else
3229 : PyErr_Format(PyExc_AttributeError,
3230 : "function ordinal %d not found",
3231 : (WORD)(size_t)name);
3232 : return NULL;
3233 : }
3234 : #else
3235 0 : address = (PPROC)ctypes_dlsym(handle, name);
3236 0 : if (!address) {
3237 : #ifdef __CYGWIN__
3238 : /* dlerror() isn't very helpful on cygwin */
3239 : PyErr_Format(PyExc_AttributeError,
3240 : "function '%s' not found (%s) ",
3241 : name);
3242 : #else
3243 0 : PyErr_SetString(PyExc_AttributeError, ctypes_dlerror());
3244 : #endif
3245 0 : return NULL;
3246 : }
3247 : #endif
3248 0 : if (!_validate_paramflags(type, paramflags))
3249 0 : return NULL;
3250 :
3251 0 : self = (PyCFuncPtrObject *)GenericPyCData_new(type, args, kwds);
3252 0 : if (!self)
3253 0 : return NULL;
3254 :
3255 0 : Py_XINCREF(paramflags);
3256 0 : self->paramflags = paramflags;
3257 :
3258 0 : *(void **)self->b_ptr = address;
3259 :
3260 0 : Py_INCREF((PyObject *)dll); /* for KeepRef */
3261 0 : if (-1 == KeepRef((CDataObject *)self, 0, dll)) {
3262 0 : Py_DECREF((PyObject *)self);
3263 0 : return NULL;
3264 : }
3265 :
3266 0 : Py_INCREF(self);
3267 0 : self->callable = (PyObject *)self;
3268 0 : return (PyObject *)self;
3269 : }
3270 :
3271 : #ifdef MS_WIN32
3272 : static PyObject *
3273 : PyCFuncPtr_FromVtblIndex(PyTypeObject *type, PyObject *args, PyObject *kwds)
3274 : {
3275 : PyCFuncPtrObject *self;
3276 : int index;
3277 : char *name = NULL;
3278 : PyObject *paramflags = NULL;
3279 : GUID *iid = NULL;
3280 : Py_ssize_t iid_len = 0;
3281 :
3282 : if (!PyArg_ParseTuple(args, "is|Oz#", &index, &name, ¶mflags, &iid, &iid_len))
3283 : return NULL;
3284 : if (paramflags == Py_None)
3285 : paramflags = NULL;
3286 :
3287 : if (!_validate_paramflags(type, paramflags))
3288 : return NULL;
3289 :
3290 : self = (PyCFuncPtrObject *)GenericPyCData_new(type, args, kwds);
3291 : self->index = index + 0x1000;
3292 : Py_XINCREF(paramflags);
3293 : self->paramflags = paramflags;
3294 : if (iid_len == sizeof(GUID))
3295 : self->iid = iid;
3296 : return (PyObject *)self;
3297 : }
3298 : #endif
3299 :
3300 : /*
3301 : PyCFuncPtr_new accepts different argument lists in addition to the standard
3302 : _basespec_ keyword arg:
3303 :
3304 : one argument form
3305 : "i" - function address
3306 : "O" - must be a callable, creates a C callable function
3307 :
3308 : two or more argument forms (the third argument is a paramflags tuple)
3309 : "(sO)|..." - (function name, dll object (with an integer handle)), paramflags
3310 : "(iO)|..." - (function ordinal, dll object (with an integer handle)), paramflags
3311 : "is|..." - vtable index, method name, creates callable calling COM vtbl
3312 : */
3313 : static PyObject *
3314 0 : PyCFuncPtr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
3315 : {
3316 : PyCFuncPtrObject *self;
3317 : PyObject *callable;
3318 : StgDictObject *dict;
3319 : CThunkObject *thunk;
3320 :
3321 0 : if (PyTuple_GET_SIZE(args) == 0)
3322 0 : return GenericPyCData_new(type, args, kwds);
3323 :
3324 0 : if (1 <= PyTuple_GET_SIZE(args) && PyTuple_Check(PyTuple_GET_ITEM(args, 0)))
3325 0 : return PyCFuncPtr_FromDll(type, args, kwds);
3326 :
3327 : #ifdef MS_WIN32
3328 : if (2 <= PyTuple_GET_SIZE(args) && PyLong_Check(PyTuple_GET_ITEM(args, 0)))
3329 : return PyCFuncPtr_FromVtblIndex(type, args, kwds);
3330 : #endif
3331 :
3332 0 : if (1 == PyTuple_GET_SIZE(args)
3333 0 : && (PyLong_Check(PyTuple_GET_ITEM(args, 0)))) {
3334 : CDataObject *ob;
3335 0 : void *ptr = PyLong_AsVoidPtr(PyTuple_GET_ITEM(args, 0));
3336 0 : if (ptr == NULL && PyErr_Occurred())
3337 0 : return NULL;
3338 0 : ob = (CDataObject *)GenericPyCData_new(type, args, kwds);
3339 0 : if (ob == NULL)
3340 0 : return NULL;
3341 0 : *(void **)ob->b_ptr = ptr;
3342 0 : return (PyObject *)ob;
3343 : }
3344 :
3345 0 : if (!PyArg_ParseTuple(args, "O", &callable))
3346 0 : return NULL;
3347 0 : if (!PyCallable_Check(callable)) {
3348 0 : PyErr_SetString(PyExc_TypeError,
3349 : "argument must be callable or integer function address");
3350 0 : return NULL;
3351 : }
3352 :
3353 : /* XXX XXX This would allow to pass additional options. For COM
3354 : method *implementations*, we would probably want different
3355 : behaviour than in 'normal' callback functions: return a HRESULT if
3356 : an exception occurs in the callback, and print the traceback not
3357 : only on the console, but also to OutputDebugString() or something
3358 : like that.
3359 : */
3360 : /*
3361 : if (kwds && PyDict_GetItemString(kwds, "options")) {
3362 : ...
3363 : }
3364 : */
3365 :
3366 0 : dict = PyType_stgdict((PyObject *)type);
3367 : /* XXXX Fails if we do: 'PyCFuncPtr(lambda x: x)' */
3368 0 : if (!dict || !dict->argtypes) {
3369 0 : PyErr_SetString(PyExc_TypeError,
3370 : "cannot construct instance of this class:"
3371 : " no argtypes");
3372 0 : return NULL;
3373 : }
3374 :
3375 0 : thunk = _ctypes_alloc_callback(callable,
3376 : dict->argtypes,
3377 : dict->restype,
3378 : dict->flags);
3379 0 : if (!thunk)
3380 0 : return NULL;
3381 :
3382 0 : self = (PyCFuncPtrObject *)GenericPyCData_new(type, args, kwds);
3383 0 : if (self == NULL) {
3384 0 : Py_DECREF(thunk);
3385 0 : return NULL;
3386 : }
3387 :
3388 0 : Py_INCREF(callable);
3389 0 : self->callable = callable;
3390 :
3391 0 : self->thunk = thunk;
3392 0 : *(void **)self->b_ptr = (void *)thunk->pcl_exec;
3393 :
3394 0 : Py_INCREF((PyObject *)thunk); /* for KeepRef */
3395 0 : if (-1 == KeepRef((CDataObject *)self, 0, (PyObject *)thunk)) {
3396 0 : Py_DECREF((PyObject *)self);
3397 0 : return NULL;
3398 : }
3399 0 : return (PyObject *)self;
3400 : }
3401 :
3402 :
3403 : /*
3404 : _byref consumes a refcount to its argument
3405 : */
3406 : static PyObject *
3407 0 : _byref(PyObject *obj)
3408 : {
3409 : PyCArgObject *parg;
3410 0 : if (!CDataObject_Check(obj)) {
3411 0 : PyErr_SetString(PyExc_TypeError,
3412 : "expected CData instance");
3413 0 : return NULL;
3414 : }
3415 :
3416 0 : parg = PyCArgObject_new();
3417 0 : if (parg == NULL) {
3418 0 : Py_DECREF(obj);
3419 0 : return NULL;
3420 : }
3421 :
3422 0 : parg->tag = 'P';
3423 0 : parg->pffi_type = &ffi_type_pointer;
3424 0 : parg->obj = obj;
3425 0 : parg->value.p = ((CDataObject *)obj)->b_ptr;
3426 0 : return (PyObject *)parg;
3427 : }
3428 :
3429 : static PyObject *
3430 0 : _get_arg(int *pindex, PyObject *name, PyObject *defval, PyObject *inargs, PyObject *kwds)
3431 : {
3432 : PyObject *v;
3433 :
3434 0 : if (*pindex < PyTuple_GET_SIZE(inargs)) {
3435 0 : v = PyTuple_GET_ITEM(inargs, *pindex);
3436 0 : ++*pindex;
3437 0 : Py_INCREF(v);
3438 0 : return v;
3439 : }
3440 0 : if (kwds && (v = PyDict_GetItem(kwds, name))) {
3441 0 : ++*pindex;
3442 0 : Py_INCREF(v);
3443 0 : return v;
3444 : }
3445 0 : if (defval) {
3446 0 : Py_INCREF(defval);
3447 0 : return defval;
3448 : }
3449 : /* we can't currently emit a better error message */
3450 0 : if (name)
3451 0 : PyErr_Format(PyExc_TypeError,
3452 : "required argument '%S' missing", name);
3453 : else
3454 0 : PyErr_Format(PyExc_TypeError,
3455 : "not enough arguments");
3456 0 : return NULL;
3457 : }
3458 :
3459 : /*
3460 : This function implements higher level functionality plus the ability to call
3461 : functions with keyword arguments by looking at parameter flags. parameter
3462 : flags is a tuple of 1, 2 or 3-tuples. The first entry in each is an integer
3463 : specifying the direction of the data transfer for this parameter - 'in',
3464 : 'out' or 'inout' (zero means the same as 'in'). The second entry is the
3465 : parameter name, and the third is the default value if the parameter is
3466 : missing in the function call.
3467 :
3468 : This function builds and returns a new tuple 'callargs' which contains the
3469 : parameters to use in the call. Items on this tuple are copied from the
3470 : 'inargs' tuple for 'in' and 'in, out' parameters, and constructed from the
3471 : 'argtypes' tuple for 'out' parameters. It also calculates numretvals which
3472 : is the number of return values for the function, outmask/inoutmask are
3473 : bitmasks containing indexes into the callargs tuple specifying which
3474 : parameters have to be returned. _build_result builds the return value of the
3475 : function.
3476 : */
3477 : static PyObject *
3478 0 : _build_callargs(PyCFuncPtrObject *self, PyObject *argtypes,
3479 : PyObject *inargs, PyObject *kwds,
3480 : int *poutmask, int *pinoutmask, unsigned int *pnumretvals)
3481 : {
3482 0 : PyObject *paramflags = self->paramflags;
3483 : PyObject *callargs;
3484 : StgDictObject *dict;
3485 : Py_ssize_t i, len;
3486 0 : int inargs_index = 0;
3487 : /* It's a little bit difficult to determine how many arguments the
3488 : function call requires/accepts. For simplicity, we count the consumed
3489 : args and compare this to the number of supplied args. */
3490 : Py_ssize_t actual_args;
3491 :
3492 0 : *poutmask = 0;
3493 0 : *pinoutmask = 0;
3494 0 : *pnumretvals = 0;
3495 :
3496 : /* Trivial cases, where we either return inargs itself, or a slice of it. */
3497 0 : if (argtypes == NULL || paramflags == NULL || PyTuple_GET_SIZE(argtypes) == 0) {
3498 : #ifdef MS_WIN32
3499 : if (self->index)
3500 : return PyTuple_GetSlice(inargs, 1, PyTuple_GET_SIZE(inargs));
3501 : #endif
3502 0 : Py_INCREF(inargs);
3503 0 : return inargs;
3504 : }
3505 :
3506 0 : len = PyTuple_GET_SIZE(argtypes);
3507 0 : callargs = PyTuple_New(len); /* the argument tuple we build */
3508 0 : if (callargs == NULL)
3509 0 : return NULL;
3510 :
3511 : #ifdef MS_WIN32
3512 : /* For a COM method, skip the first arg */
3513 : if (self->index) {
3514 : inargs_index = 1;
3515 : }
3516 : #endif
3517 0 : for (i = 0; i < len; ++i) {
3518 0 : PyObject *item = PyTuple_GET_ITEM(paramflags, i);
3519 : PyObject *ob;
3520 : int flag;
3521 0 : PyObject *name = NULL;
3522 0 : PyObject *defval = NULL;
3523 :
3524 : /* This way seems to be ~2 us faster than the PyArg_ParseTuple
3525 : calls below. */
3526 : /* We HAVE already checked that the tuple can be parsed with "i|ZO", so... */
3527 0 : Py_ssize_t tsize = PyTuple_GET_SIZE(item);
3528 0 : flag = PyLong_AS_LONG(PyTuple_GET_ITEM(item, 0));
3529 0 : name = tsize > 1 ? PyTuple_GET_ITEM(item, 1) : NULL;
3530 0 : defval = tsize > 2 ? PyTuple_GET_ITEM(item, 2) : NULL;
3531 :
3532 0 : switch (flag & (PARAMFLAG_FIN | PARAMFLAG_FOUT | PARAMFLAG_FLCID)) {
3533 : case PARAMFLAG_FIN | PARAMFLAG_FLCID:
3534 : /* ['in', 'lcid'] parameter. Always taken from defval,
3535 : if given, else the integer 0. */
3536 0 : if (defval == NULL) {
3537 0 : defval = PyLong_FromLong(0);
3538 0 : if (defval == NULL)
3539 0 : goto error;
3540 : } else
3541 0 : Py_INCREF(defval);
3542 0 : PyTuple_SET_ITEM(callargs, i, defval);
3543 0 : break;
3544 : case (PARAMFLAG_FIN | PARAMFLAG_FOUT):
3545 0 : *pinoutmask |= (1 << i); /* mark as inout arg */
3546 0 : (*pnumretvals)++;
3547 : /* fall through to PARAMFLAG_FIN... */
3548 : case 0:
3549 : case PARAMFLAG_FIN:
3550 : /* 'in' parameter. Copy it from inargs. */
3551 0 : ob =_get_arg(&inargs_index, name, defval, inargs, kwds);
3552 0 : if (ob == NULL)
3553 0 : goto error;
3554 0 : PyTuple_SET_ITEM(callargs, i, ob);
3555 0 : break;
3556 : case PARAMFLAG_FOUT:
3557 : /* XXX Refactor this code into a separate function. */
3558 : /* 'out' parameter.
3559 : argtypes[i] must be a POINTER to a c type.
3560 :
3561 : Cannot by supplied in inargs, but a defval will be used
3562 : if available. XXX Should we support getting it from kwds?
3563 : */
3564 0 : if (defval) {
3565 : /* XXX Using mutable objects as defval will
3566 : make the function non-threadsafe, unless we
3567 : copy the object in each invocation */
3568 0 : Py_INCREF(defval);
3569 0 : PyTuple_SET_ITEM(callargs, i, defval);
3570 0 : *poutmask |= (1 << i); /* mark as out arg */
3571 0 : (*pnumretvals)++;
3572 0 : break;
3573 : }
3574 0 : ob = PyTuple_GET_ITEM(argtypes, i);
3575 0 : dict = PyType_stgdict(ob);
3576 0 : if (dict == NULL) {
3577 : /* Cannot happen: _validate_paramflags()
3578 : would not accept such an object */
3579 0 : PyErr_Format(PyExc_RuntimeError,
3580 : "NULL stgdict unexpected");
3581 0 : goto error;
3582 : }
3583 0 : if (PyUnicode_Check(dict->proto)) {
3584 0 : PyErr_Format(
3585 : PyExc_TypeError,
3586 : "%s 'out' parameter must be passed as default value",
3587 : ((PyTypeObject *)ob)->tp_name);
3588 0 : goto error;
3589 : }
3590 0 : if (PyCArrayTypeObject_Check(ob))
3591 0 : ob = PyObject_CallObject(ob, NULL);
3592 : else
3593 : /* Create an instance of the pointed-to type */
3594 0 : ob = PyObject_CallObject(dict->proto, NULL);
3595 : /*
3596 : XXX Is the following correct any longer?
3597 : We must not pass a byref() to the array then but
3598 : the array instance itself. Then, we cannot retrive
3599 : the result from the PyCArgObject.
3600 : */
3601 0 : if (ob == NULL)
3602 0 : goto error;
3603 : /* The .from_param call that will ocurr later will pass this
3604 : as a byref parameter. */
3605 0 : PyTuple_SET_ITEM(callargs, i, ob);
3606 0 : *poutmask |= (1 << i); /* mark as out arg */
3607 0 : (*pnumretvals)++;
3608 0 : break;
3609 : default:
3610 0 : PyErr_Format(PyExc_ValueError,
3611 : "paramflag %d not yet implemented", flag);
3612 0 : goto error;
3613 : break;
3614 : }
3615 : }
3616 :
3617 : /* We have counted the arguments we have consumed in 'inargs_index'. This
3618 : must be the same as len(inargs) + len(kwds), otherwise we have
3619 : either too much or not enough arguments. */
3620 :
3621 0 : actual_args = PyTuple_GET_SIZE(inargs) + (kwds ? PyDict_Size(kwds) : 0);
3622 0 : if (actual_args != inargs_index) {
3623 : /* When we have default values or named parameters, this error
3624 : message is misleading. See unittests/test_paramflags.py
3625 : */
3626 0 : PyErr_Format(PyExc_TypeError,
3627 : "call takes exactly %d arguments (%zd given)",
3628 : inargs_index, actual_args);
3629 0 : goto error;
3630 : }
3631 :
3632 : /* outmask is a bitmask containing indexes into callargs. Items at
3633 : these indexes contain values to return.
3634 : */
3635 0 : return callargs;
3636 : error:
3637 0 : Py_DECREF(callargs);
3638 0 : return NULL;
3639 : }
3640 :
3641 : /* See also:
3642 : http://msdn.microsoft.com/library/en-us/com/html/769127a1-1a14-4ed4-9d38-7cf3e571b661.asp
3643 : */
3644 : /*
3645 : Build return value of a function.
3646 :
3647 : Consumes the refcount on result and callargs.
3648 : */
3649 : static PyObject *
3650 0 : _build_result(PyObject *result, PyObject *callargs,
3651 : int outmask, int inoutmask, unsigned int numretvals)
3652 : {
3653 : unsigned int i, index;
3654 : int bit;
3655 0 : PyObject *tup = NULL;
3656 :
3657 0 : if (callargs == NULL)
3658 0 : return result;
3659 0 : if (result == NULL || numretvals == 0) {
3660 0 : Py_DECREF(callargs);
3661 0 : return result;
3662 : }
3663 0 : Py_DECREF(result);
3664 :
3665 : /* tup will not be allocated if numretvals == 1 */
3666 : /* allocate tuple to hold the result */
3667 0 : if (numretvals > 1) {
3668 0 : tup = PyTuple_New(numretvals);
3669 0 : if (tup == NULL) {
3670 0 : Py_DECREF(callargs);
3671 0 : return NULL;
3672 : }
3673 : }
3674 :
3675 0 : index = 0;
3676 0 : for (bit = 1, i = 0; i < 32; ++i, bit <<= 1) {
3677 : PyObject *v;
3678 0 : if (bit & inoutmask) {
3679 0 : v = PyTuple_GET_ITEM(callargs, i);
3680 0 : Py_INCREF(v);
3681 0 : if (numretvals == 1) {
3682 0 : Py_DECREF(callargs);
3683 0 : return v;
3684 : }
3685 0 : PyTuple_SET_ITEM(tup, index, v);
3686 0 : index++;
3687 0 : } else if (bit & outmask) {
3688 : _Py_IDENTIFIER(__ctypes_from_outparam__);
3689 :
3690 0 : v = PyTuple_GET_ITEM(callargs, i);
3691 0 : v = _PyObject_CallMethodId(v, &PyId___ctypes_from_outparam__, NULL);
3692 0 : if (v == NULL || numretvals == 1) {
3693 0 : Py_DECREF(callargs);
3694 0 : return v;
3695 : }
3696 0 : PyTuple_SET_ITEM(tup, index, v);
3697 0 : index++;
3698 : }
3699 0 : if (index == numretvals)
3700 0 : break;
3701 : }
3702 :
3703 0 : Py_DECREF(callargs);
3704 0 : return tup;
3705 : }
3706 :
3707 : static PyObject *
3708 0 : PyCFuncPtr_call(PyCFuncPtrObject *self, PyObject *inargs, PyObject *kwds)
3709 : {
3710 : PyObject *restype;
3711 : PyObject *converters;
3712 : PyObject *checker;
3713 : PyObject *argtypes;
3714 0 : StgDictObject *dict = PyObject_stgdict((PyObject *)self);
3715 : PyObject *result;
3716 : PyObject *callargs;
3717 : PyObject *errcheck;
3718 : #ifdef MS_WIN32
3719 : IUnknown *piunk = NULL;
3720 : #endif
3721 0 : void *pProc = NULL;
3722 :
3723 : int inoutmask;
3724 : int outmask;
3725 : unsigned int numretvals;
3726 :
3727 : assert(dict); /* Cannot be NULL for PyCFuncPtrObject instances */
3728 0 : restype = self->restype ? self->restype : dict->restype;
3729 0 : converters = self->converters ? self->converters : dict->converters;
3730 0 : checker = self->checker ? self->checker : dict->checker;
3731 0 : argtypes = self->argtypes ? self->argtypes : dict->argtypes;
3732 : /* later, we probably want to have an errcheck field in stgdict */
3733 0 : errcheck = self->errcheck /* ? self->errcheck : dict->errcheck */;
3734 :
3735 :
3736 0 : pProc = *(void **)self->b_ptr;
3737 : #ifdef MS_WIN32
3738 : if (self->index) {
3739 : /* It's a COM method */
3740 : CDataObject *this;
3741 : this = (CDataObject *)PyTuple_GetItem(inargs, 0); /* borrowed ref! */
3742 : if (!this) {
3743 : PyErr_SetString(PyExc_ValueError,
3744 : "native com method call without 'this' parameter");
3745 : return NULL;
3746 : }
3747 : if (!CDataObject_Check(this)) {
3748 : PyErr_SetString(PyExc_TypeError,
3749 : "Expected a COM this pointer as first argument");
3750 : return NULL;
3751 : }
3752 : /* there should be more checks? No, in Python */
3753 : /* First arg is an pointer to an interface instance */
3754 : if (!this->b_ptr || *(void **)this->b_ptr == NULL) {
3755 : PyErr_SetString(PyExc_ValueError,
3756 : "NULL COM pointer access");
3757 : return NULL;
3758 : }
3759 : piunk = *(IUnknown **)this->b_ptr;
3760 : if (NULL == piunk->lpVtbl) {
3761 : PyErr_SetString(PyExc_ValueError,
3762 : "COM method call without VTable");
3763 : return NULL;
3764 : }
3765 : pProc = ((void **)piunk->lpVtbl)[self->index - 0x1000];
3766 : }
3767 : #endif
3768 0 : callargs = _build_callargs(self, argtypes,
3769 : inargs, kwds,
3770 : &outmask, &inoutmask, &numretvals);
3771 0 : if (callargs == NULL)
3772 0 : return NULL;
3773 :
3774 0 : if (converters) {
3775 0 : int required = Py_SAFE_DOWNCAST(PyTuple_GET_SIZE(converters),
3776 : Py_ssize_t, int);
3777 0 : int actual = Py_SAFE_DOWNCAST(PyTuple_GET_SIZE(callargs),
3778 : Py_ssize_t, int);
3779 :
3780 0 : if ((dict->flags & FUNCFLAG_CDECL) == FUNCFLAG_CDECL) {
3781 : /* For cdecl functions, we allow more actual arguments
3782 : than the length of the argtypes tuple.
3783 : */
3784 0 : if (required > actual) {
3785 0 : Py_DECREF(callargs);
3786 0 : PyErr_Format(PyExc_TypeError,
3787 : "this function takes at least %d argument%s (%d given)",
3788 : required,
3789 : required == 1 ? "" : "s",
3790 : actual);
3791 0 : return NULL;
3792 : }
3793 0 : } else if (required != actual) {
3794 0 : Py_DECREF(callargs);
3795 0 : PyErr_Format(PyExc_TypeError,
3796 : "this function takes %d argument%s (%d given)",
3797 : required,
3798 : required == 1 ? "" : "s",
3799 : actual);
3800 0 : return NULL;
3801 : }
3802 : }
3803 :
3804 0 : result = _ctypes_callproc(pProc,
3805 : callargs,
3806 : #ifdef MS_WIN32
3807 : piunk,
3808 : self->iid,
3809 : #endif
3810 : dict->flags,
3811 : converters,
3812 : restype,
3813 : checker);
3814 : /* The 'errcheck' protocol */
3815 0 : if (result != NULL && errcheck) {
3816 0 : PyObject *v = PyObject_CallFunctionObjArgs(errcheck,
3817 : result,
3818 : self,
3819 : callargs,
3820 : NULL);
3821 : /* If the errcheck funtion failed, return NULL.
3822 : If the errcheck function returned callargs unchanged,
3823 : continue normal processing.
3824 : If the errcheck function returned something else,
3825 : use that as result.
3826 : */
3827 0 : if (v == NULL || v != callargs) {
3828 0 : Py_DECREF(result);
3829 0 : Py_DECREF(callargs);
3830 0 : return v;
3831 : }
3832 0 : Py_DECREF(v);
3833 : }
3834 :
3835 0 : return _build_result(result, callargs,
3836 : outmask, inoutmask, numretvals);
3837 : }
3838 :
3839 : static int
3840 0 : PyCFuncPtr_traverse(PyCFuncPtrObject *self, visitproc visit, void *arg)
3841 : {
3842 0 : Py_VISIT(self->callable);
3843 0 : Py_VISIT(self->restype);
3844 0 : Py_VISIT(self->checker);
3845 0 : Py_VISIT(self->errcheck);
3846 0 : Py_VISIT(self->argtypes);
3847 0 : Py_VISIT(self->converters);
3848 0 : Py_VISIT(self->paramflags);
3849 0 : Py_VISIT(self->thunk);
3850 0 : return PyCData_traverse((CDataObject *)self, visit, arg);
3851 : }
3852 :
3853 : static int
3854 0 : PyCFuncPtr_clear(PyCFuncPtrObject *self)
3855 : {
3856 0 : Py_CLEAR(self->callable);
3857 0 : Py_CLEAR(self->restype);
3858 0 : Py_CLEAR(self->checker);
3859 0 : Py_CLEAR(self->errcheck);
3860 0 : Py_CLEAR(self->argtypes);
3861 0 : Py_CLEAR(self->converters);
3862 0 : Py_CLEAR(self->paramflags);
3863 0 : Py_CLEAR(self->thunk);
3864 0 : return PyCData_clear((CDataObject *)self);
3865 : }
3866 :
3867 : static void
3868 0 : PyCFuncPtr_dealloc(PyCFuncPtrObject *self)
3869 : {
3870 0 : PyCFuncPtr_clear(self);
3871 0 : Py_TYPE(self)->tp_free((PyObject *)self);
3872 0 : }
3873 :
3874 : static PyObject *
3875 0 : PyCFuncPtr_repr(PyCFuncPtrObject *self)
3876 : {
3877 : #ifdef MS_WIN32
3878 : if (self->index)
3879 : return PyUnicode_FromFormat("<COM method offset %d: %s at %p>",
3880 : self->index - 0x1000,
3881 : Py_TYPE(self)->tp_name,
3882 : self);
3883 : #endif
3884 0 : return PyUnicode_FromFormat("<%s object at %p>",
3885 0 : Py_TYPE(self)->tp_name,
3886 : self);
3887 : }
3888 :
3889 : static int
3890 0 : PyCFuncPtr_bool(PyCFuncPtrObject *self)
3891 : {
3892 0 : return ((*(void **)self->b_ptr != NULL)
3893 : #ifdef MS_WIN32
3894 : || (self->index != 0)
3895 : #endif
3896 : );
3897 : }
3898 :
3899 : static PyNumberMethods PyCFuncPtr_as_number = {
3900 : 0, /* nb_add */
3901 : 0, /* nb_subtract */
3902 : 0, /* nb_multiply */
3903 : 0, /* nb_remainder */
3904 : 0, /* nb_divmod */
3905 : 0, /* nb_power */
3906 : 0, /* nb_negative */
3907 : 0, /* nb_positive */
3908 : 0, /* nb_absolute */
3909 : (inquiry)PyCFuncPtr_bool, /* nb_bool */
3910 : };
3911 :
3912 : PyTypeObject PyCFuncPtr_Type = {
3913 : PyVarObject_HEAD_INIT(NULL, 0)
3914 : "_ctypes.PyCFuncPtr",
3915 : sizeof(PyCFuncPtrObject), /* tp_basicsize */
3916 : 0, /* tp_itemsize */
3917 : (destructor)PyCFuncPtr_dealloc, /* tp_dealloc */
3918 : 0, /* tp_print */
3919 : 0, /* tp_getattr */
3920 : 0, /* tp_setattr */
3921 : 0, /* tp_reserved */
3922 : (reprfunc)PyCFuncPtr_repr, /* tp_repr */
3923 : &PyCFuncPtr_as_number, /* tp_as_number */
3924 : 0, /* tp_as_sequence */
3925 : 0, /* tp_as_mapping */
3926 : 0, /* tp_hash */
3927 : (ternaryfunc)PyCFuncPtr_call, /* tp_call */
3928 : 0, /* tp_str */
3929 : 0, /* tp_getattro */
3930 : 0, /* tp_setattro */
3931 : &PyCData_as_buffer, /* tp_as_buffer */
3932 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
3933 : "Function Pointer", /* tp_doc */
3934 : (traverseproc)PyCFuncPtr_traverse, /* tp_traverse */
3935 : (inquiry)PyCFuncPtr_clear, /* tp_clear */
3936 : 0, /* tp_richcompare */
3937 : 0, /* tp_weaklistoffset */
3938 : 0, /* tp_iter */
3939 : 0, /* tp_iternext */
3940 : 0, /* tp_methods */
3941 : 0, /* tp_members */
3942 : PyCFuncPtr_getsets, /* tp_getset */
3943 : 0, /* tp_base */
3944 : 0, /* tp_dict */
3945 : 0, /* tp_descr_get */
3946 : 0, /* tp_descr_set */
3947 : 0, /* tp_dictoffset */
3948 : 0, /* tp_init */
3949 : 0, /* tp_alloc */
3950 : PyCFuncPtr_new, /* tp_new */
3951 : 0, /* tp_free */
3952 : };
3953 :
3954 : /*****************************************************************/
3955 : /*
3956 : Struct_Type
3957 : */
3958 : /*
3959 : This function is called to initialize a Structure or Union with positional
3960 : arguments. It calls itself recursively for all Structure or Union base
3961 : classes, then retrieves the _fields_ member to associate the argument
3962 : position with the correct field name.
3963 :
3964 : Returns -1 on error, or the index of next argument on success.
3965 : */
3966 : static Py_ssize_t
3967 0 : _init_pos_args(PyObject *self, PyTypeObject *type,
3968 : PyObject *args, PyObject *kwds,
3969 : Py_ssize_t index)
3970 : {
3971 : StgDictObject *dict;
3972 : PyObject *fields;
3973 : Py_ssize_t i;
3974 :
3975 0 : if (PyType_stgdict((PyObject *)type->tp_base)) {
3976 0 : index = _init_pos_args(self, type->tp_base,
3977 : args, kwds,
3978 : index);
3979 0 : if (index == -1)
3980 0 : return -1;
3981 : }
3982 :
3983 0 : dict = PyType_stgdict((PyObject *)type);
3984 0 : fields = PyDict_GetItemString((PyObject *)dict, "_fields_");
3985 0 : if (fields == NULL)
3986 0 : return index;
3987 :
3988 0 : for (i = 0;
3989 0 : i < dict->length && (i+index) < PyTuple_GET_SIZE(args);
3990 0 : ++i) {
3991 0 : PyObject *pair = PySequence_GetItem(fields, i);
3992 : PyObject *name, *val;
3993 : int res;
3994 0 : if (!pair)
3995 0 : return -1;
3996 0 : name = PySequence_GetItem(pair, 0);
3997 0 : if (!name) {
3998 0 : Py_DECREF(pair);
3999 0 : return -1;
4000 : }
4001 0 : val = PyTuple_GET_ITEM(args, i + index);
4002 0 : if (kwds && PyDict_GetItem(kwds, name)) {
4003 0 : char *field = PyBytes_AsString(name);
4004 0 : if (field == NULL) {
4005 0 : PyErr_Clear();
4006 0 : field = "???";
4007 : }
4008 0 : PyErr_Format(PyExc_TypeError,
4009 : "duplicate values for field '%s'",
4010 : field);
4011 0 : Py_DECREF(pair);
4012 0 : Py_DECREF(name);
4013 0 : return -1;
4014 : }
4015 :
4016 0 : res = PyObject_SetAttr(self, name, val);
4017 0 : Py_DECREF(pair);
4018 0 : Py_DECREF(name);
4019 0 : if (res == -1)
4020 0 : return -1;
4021 : }
4022 0 : return index + dict->length;
4023 : }
4024 :
4025 : static int
4026 0 : Struct_init(PyObject *self, PyObject *args, PyObject *kwds)
4027 : {
4028 : /* Optimization possible: Store the attribute names _fields_[x][0]
4029 : * in C accessible fields somewhere ?
4030 : */
4031 0 : if (!PyTuple_Check(args)) {
4032 0 : PyErr_SetString(PyExc_TypeError,
4033 : "args not a tuple?");
4034 0 : return -1;
4035 : }
4036 0 : if (PyTuple_GET_SIZE(args)) {
4037 0 : int res = _init_pos_args(self, Py_TYPE(self),
4038 : args, kwds, 0);
4039 0 : if (res == -1)
4040 0 : return -1;
4041 0 : if (res < PyTuple_GET_SIZE(args)) {
4042 0 : PyErr_SetString(PyExc_TypeError,
4043 : "too many initializers");
4044 0 : return -1;
4045 : }
4046 : }
4047 :
4048 0 : if (kwds) {
4049 : PyObject *key, *value;
4050 0 : Py_ssize_t pos = 0;
4051 0 : while(PyDict_Next(kwds, &pos, &key, &value)) {
4052 0 : if (-1 == PyObject_SetAttr(self, key, value))
4053 0 : return -1;
4054 : }
4055 : }
4056 0 : return 0;
4057 : }
4058 :
4059 : static PyTypeObject Struct_Type = {
4060 : PyVarObject_HEAD_INIT(NULL, 0)
4061 : "_ctypes.Structure",
4062 : sizeof(CDataObject), /* tp_basicsize */
4063 : 0, /* tp_itemsize */
4064 : 0, /* tp_dealloc */
4065 : 0, /* tp_print */
4066 : 0, /* tp_getattr */
4067 : 0, /* tp_setattr */
4068 : 0, /* tp_reserved */
4069 : 0, /* tp_repr */
4070 : 0, /* tp_as_number */
4071 : 0, /* tp_as_sequence */
4072 : 0, /* tp_as_mapping */
4073 : 0, /* tp_hash */
4074 : 0, /* tp_call */
4075 : 0, /* tp_str */
4076 : 0, /* tp_getattro */
4077 : 0, /* tp_setattro */
4078 : &PyCData_as_buffer, /* tp_as_buffer */
4079 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
4080 : "Structure base class", /* tp_doc */
4081 : (traverseproc)PyCData_traverse, /* tp_traverse */
4082 : (inquiry)PyCData_clear, /* tp_clear */
4083 : 0, /* tp_richcompare */
4084 : 0, /* tp_weaklistoffset */
4085 : 0, /* tp_iter */
4086 : 0, /* tp_iternext */
4087 : 0, /* tp_methods */
4088 : 0, /* tp_members */
4089 : 0, /* tp_getset */
4090 : 0, /* tp_base */
4091 : 0, /* tp_dict */
4092 : 0, /* tp_descr_get */
4093 : 0, /* tp_descr_set */
4094 : 0, /* tp_dictoffset */
4095 : Struct_init, /* tp_init */
4096 : 0, /* tp_alloc */
4097 : GenericPyCData_new, /* tp_new */
4098 : 0, /* tp_free */
4099 : };
4100 :
4101 : static PyTypeObject Union_Type = {
4102 : PyVarObject_HEAD_INIT(NULL, 0)
4103 : "_ctypes.Union",
4104 : sizeof(CDataObject), /* tp_basicsize */
4105 : 0, /* tp_itemsize */
4106 : 0, /* tp_dealloc */
4107 : 0, /* tp_print */
4108 : 0, /* tp_getattr */
4109 : 0, /* tp_setattr */
4110 : 0, /* tp_reserved */
4111 : 0, /* tp_repr */
4112 : 0, /* tp_as_number */
4113 : 0, /* tp_as_sequence */
4114 : 0, /* tp_as_mapping */
4115 : 0, /* tp_hash */
4116 : 0, /* tp_call */
4117 : 0, /* tp_str */
4118 : 0, /* tp_getattro */
4119 : 0, /* tp_setattro */
4120 : &PyCData_as_buffer, /* tp_as_buffer */
4121 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
4122 : "Union base class", /* tp_doc */
4123 : (traverseproc)PyCData_traverse, /* tp_traverse */
4124 : (inquiry)PyCData_clear, /* tp_clear */
4125 : 0, /* tp_richcompare */
4126 : 0, /* tp_weaklistoffset */
4127 : 0, /* tp_iter */
4128 : 0, /* tp_iternext */
4129 : 0, /* tp_methods */
4130 : 0, /* tp_members */
4131 : 0, /* tp_getset */
4132 : 0, /* tp_base */
4133 : 0, /* tp_dict */
4134 : 0, /* tp_descr_get */
4135 : 0, /* tp_descr_set */
4136 : 0, /* tp_dictoffset */
4137 : Struct_init, /* tp_init */
4138 : 0, /* tp_alloc */
4139 : GenericPyCData_new, /* tp_new */
4140 : 0, /* tp_free */
4141 : };
4142 :
4143 :
4144 : /******************************************************************/
4145 : /*
4146 : PyCArray_Type
4147 : */
4148 : static int
4149 0 : Array_init(CDataObject *self, PyObject *args, PyObject *kw)
4150 : {
4151 : Py_ssize_t i;
4152 : Py_ssize_t n;
4153 :
4154 0 : if (!PyTuple_Check(args)) {
4155 0 : PyErr_SetString(PyExc_TypeError,
4156 : "args not a tuple?");
4157 0 : return -1;
4158 : }
4159 0 : n = PyTuple_GET_SIZE(args);
4160 0 : for (i = 0; i < n; ++i) {
4161 : PyObject *v;
4162 0 : v = PyTuple_GET_ITEM(args, i);
4163 0 : if (-1 == PySequence_SetItem((PyObject *)self, i, v))
4164 0 : return -1;
4165 : }
4166 0 : return 0;
4167 : }
4168 :
4169 : static PyObject *
4170 0 : Array_item(PyObject *_self, Py_ssize_t index)
4171 : {
4172 0 : CDataObject *self = (CDataObject *)_self;
4173 : Py_ssize_t offset, size;
4174 : StgDictObject *stgdict;
4175 :
4176 :
4177 0 : if (index < 0 || index >= self->b_length) {
4178 0 : PyErr_SetString(PyExc_IndexError,
4179 : "invalid index");
4180 0 : return NULL;
4181 : }
4182 :
4183 0 : stgdict = PyObject_stgdict((PyObject *)self);
4184 : assert(stgdict); /* Cannot be NULL for array instances */
4185 : /* Would it be clearer if we got the item size from
4186 : stgdict->proto's stgdict?
4187 : */
4188 0 : size = stgdict->size / stgdict->length;
4189 0 : offset = index * size;
4190 :
4191 0 : return PyCData_get(stgdict->proto, stgdict->getfunc, (PyObject *)self,
4192 0 : index, size, self->b_ptr + offset);
4193 : }
4194 :
4195 : static PyObject *
4196 0 : Array_subscript(PyObject *_self, PyObject *item)
4197 : {
4198 0 : CDataObject *self = (CDataObject *)_self;
4199 :
4200 0 : if (PyIndex_Check(item)) {
4201 0 : Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
4202 :
4203 0 : if (i == -1 && PyErr_Occurred())
4204 0 : return NULL;
4205 0 : if (i < 0)
4206 0 : i += self->b_length;
4207 0 : return Array_item(_self, i);
4208 : }
4209 0 : else if PySlice_Check(item) {
4210 : StgDictObject *stgdict, *itemdict;
4211 : PyObject *proto;
4212 : PyObject *np;
4213 : Py_ssize_t start, stop, step, slicelen, cur, i;
4214 :
4215 0 : if (PySlice_GetIndicesEx(item,
4216 : self->b_length, &start, &stop,
4217 : &step, &slicelen) < 0) {
4218 0 : return NULL;
4219 : }
4220 :
4221 0 : stgdict = PyObject_stgdict((PyObject *)self);
4222 : assert(stgdict); /* Cannot be NULL for array object instances */
4223 0 : proto = stgdict->proto;
4224 0 : itemdict = PyType_stgdict(proto);
4225 : assert(itemdict); /* proto is the item type of the array, a
4226 : ctypes type, so this cannot be NULL */
4227 :
4228 0 : if (itemdict->getfunc == _ctypes_get_fielddesc("c")->getfunc) {
4229 0 : char *ptr = (char *)self->b_ptr;
4230 : char *dest;
4231 :
4232 0 : if (slicelen <= 0)
4233 0 : return PyBytes_FromStringAndSize("", 0);
4234 0 : if (step == 1) {
4235 0 : return PyBytes_FromStringAndSize(ptr + start,
4236 : slicelen);
4237 : }
4238 0 : dest = (char *)PyMem_Malloc(slicelen);
4239 :
4240 0 : if (dest == NULL)
4241 0 : return PyErr_NoMemory();
4242 :
4243 0 : for (cur = start, i = 0; i < slicelen;
4244 0 : cur += step, i++) {
4245 0 : dest[i] = ptr[cur];
4246 : }
4247 :
4248 0 : np = PyBytes_FromStringAndSize(dest, slicelen);
4249 0 : PyMem_Free(dest);
4250 0 : return np;
4251 : }
4252 : #ifdef CTYPES_UNICODE
4253 0 : if (itemdict->getfunc == _ctypes_get_fielddesc("u")->getfunc) {
4254 0 : wchar_t *ptr = (wchar_t *)self->b_ptr;
4255 : wchar_t *dest;
4256 :
4257 0 : if (slicelen <= 0)
4258 0 : return PyUnicode_New(0, 0);
4259 0 : if (step == 1) {
4260 0 : return PyUnicode_FromWideChar(ptr + start,
4261 : slicelen);
4262 : }
4263 :
4264 0 : dest = (wchar_t *)PyMem_Malloc(
4265 : slicelen * sizeof(wchar_t));
4266 :
4267 0 : for (cur = start, i = 0; i < slicelen;
4268 0 : cur += step, i++) {
4269 0 : dest[i] = ptr[cur];
4270 : }
4271 :
4272 0 : np = PyUnicode_FromWideChar(dest, slicelen);
4273 0 : PyMem_Free(dest);
4274 0 : return np;
4275 : }
4276 : #endif
4277 :
4278 0 : np = PyList_New(slicelen);
4279 0 : if (np == NULL)
4280 0 : return NULL;
4281 :
4282 0 : for (cur = start, i = 0; i < slicelen;
4283 0 : cur += step, i++) {
4284 0 : PyObject *v = Array_item(_self, cur);
4285 0 : PyList_SET_ITEM(np, i, v);
4286 : }
4287 0 : return np;
4288 : }
4289 : else {
4290 0 : PyErr_SetString(PyExc_TypeError,
4291 : "indices must be integers");
4292 0 : return NULL;
4293 : }
4294 :
4295 : }
4296 :
4297 : static int
4298 0 : Array_ass_item(PyObject *_self, Py_ssize_t index, PyObject *value)
4299 : {
4300 0 : CDataObject *self = (CDataObject *)_self;
4301 : Py_ssize_t size, offset;
4302 : StgDictObject *stgdict;
4303 : char *ptr;
4304 :
4305 0 : if (value == NULL) {
4306 0 : PyErr_SetString(PyExc_TypeError,
4307 : "Array does not support item deletion");
4308 0 : return -1;
4309 : }
4310 :
4311 0 : stgdict = PyObject_stgdict((PyObject *)self);
4312 : assert(stgdict); /* Cannot be NULL for array object instances */
4313 0 : if (index < 0 || index >= stgdict->length) {
4314 0 : PyErr_SetString(PyExc_IndexError,
4315 : "invalid index");
4316 0 : return -1;
4317 : }
4318 0 : size = stgdict->size / stgdict->length;
4319 0 : offset = index * size;
4320 0 : ptr = self->b_ptr + offset;
4321 :
4322 0 : return PyCData_set((PyObject *)self, stgdict->proto, stgdict->setfunc, value,
4323 : index, size, ptr);
4324 : }
4325 :
4326 : static int
4327 0 : Array_ass_subscript(PyObject *_self, PyObject *item, PyObject *value)
4328 : {
4329 0 : CDataObject *self = (CDataObject *)_self;
4330 :
4331 0 : if (value == NULL) {
4332 0 : PyErr_SetString(PyExc_TypeError,
4333 : "Array does not support item deletion");
4334 0 : return -1;
4335 : }
4336 :
4337 0 : if (PyIndex_Check(item)) {
4338 0 : Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
4339 :
4340 0 : if (i == -1 && PyErr_Occurred())
4341 0 : return -1;
4342 0 : if (i < 0)
4343 0 : i += self->b_length;
4344 0 : return Array_ass_item(_self, i, value);
4345 : }
4346 0 : else if (PySlice_Check(item)) {
4347 : Py_ssize_t start, stop, step, slicelen, otherlen, i, cur;
4348 :
4349 0 : if (PySlice_GetIndicesEx(item,
4350 : self->b_length, &start, &stop,
4351 : &step, &slicelen) < 0) {
4352 0 : return -1;
4353 : }
4354 0 : if ((step < 0 && start < stop) ||
4355 0 : (step > 0 && start > stop))
4356 0 : stop = start;
4357 :
4358 0 : otherlen = PySequence_Length(value);
4359 0 : if (otherlen != slicelen) {
4360 0 : PyErr_SetString(PyExc_ValueError,
4361 : "Can only assign sequence of same size");
4362 0 : return -1;
4363 : }
4364 0 : for (cur = start, i = 0; i < otherlen; cur += step, i++) {
4365 0 : PyObject *item = PySequence_GetItem(value, i);
4366 : int result;
4367 0 : if (item == NULL)
4368 0 : return -1;
4369 0 : result = Array_ass_item(_self, cur, item);
4370 0 : Py_DECREF(item);
4371 0 : if (result == -1)
4372 0 : return -1;
4373 : }
4374 0 : return 0;
4375 : }
4376 : else {
4377 0 : PyErr_SetString(PyExc_TypeError,
4378 : "indices must be integer");
4379 0 : return -1;
4380 : }
4381 : }
4382 :
4383 : static Py_ssize_t
4384 0 : Array_length(PyObject *_self)
4385 : {
4386 0 : CDataObject *self = (CDataObject *)_self;
4387 0 : return self->b_length;
4388 : }
4389 :
4390 : static PySequenceMethods Array_as_sequence = {
4391 : Array_length, /* sq_length; */
4392 : 0, /* sq_concat; */
4393 : 0, /* sq_repeat; */
4394 : Array_item, /* sq_item; */
4395 : 0, /* sq_slice; */
4396 : Array_ass_item, /* sq_ass_item; */
4397 : 0, /* sq_ass_slice; */
4398 : 0, /* sq_contains; */
4399 :
4400 : 0, /* sq_inplace_concat; */
4401 : 0, /* sq_inplace_repeat; */
4402 : };
4403 :
4404 : static PyMappingMethods Array_as_mapping = {
4405 : Array_length,
4406 : Array_subscript,
4407 : Array_ass_subscript,
4408 : };
4409 :
4410 : PyTypeObject PyCArray_Type = {
4411 : PyVarObject_HEAD_INIT(NULL, 0)
4412 : "_ctypes.Array",
4413 : sizeof(CDataObject), /* tp_basicsize */
4414 : 0, /* tp_itemsize */
4415 : 0, /* tp_dealloc */
4416 : 0, /* tp_print */
4417 : 0, /* tp_getattr */
4418 : 0, /* tp_setattr */
4419 : 0, /* tp_reserved */
4420 : 0, /* tp_repr */
4421 : 0, /* tp_as_number */
4422 : &Array_as_sequence, /* tp_as_sequence */
4423 : &Array_as_mapping, /* tp_as_mapping */
4424 : 0, /* tp_hash */
4425 : 0, /* tp_call */
4426 : 0, /* tp_str */
4427 : 0, /* tp_getattro */
4428 : 0, /* tp_setattro */
4429 : &PyCData_as_buffer, /* tp_as_buffer */
4430 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
4431 : "XXX to be provided", /* tp_doc */
4432 : (traverseproc)PyCData_traverse, /* tp_traverse */
4433 : (inquiry)PyCData_clear, /* tp_clear */
4434 : 0, /* tp_richcompare */
4435 : 0, /* tp_weaklistoffset */
4436 : 0, /* tp_iter */
4437 : 0, /* tp_iternext */
4438 : 0, /* tp_methods */
4439 : 0, /* tp_members */
4440 : 0, /* tp_getset */
4441 : 0, /* tp_base */
4442 : 0, /* tp_dict */
4443 : 0, /* tp_descr_get */
4444 : 0, /* tp_descr_set */
4445 : 0, /* tp_dictoffset */
4446 : (initproc)Array_init, /* tp_init */
4447 : 0, /* tp_alloc */
4448 : GenericPyCData_new, /* tp_new */
4449 : 0, /* tp_free */
4450 : };
4451 :
4452 : PyObject *
4453 0 : PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length)
4454 : {
4455 : static PyObject *cache;
4456 : PyObject *key;
4457 : PyObject *result;
4458 : char name[256];
4459 : PyObject *len;
4460 :
4461 0 : if (cache == NULL) {
4462 0 : cache = PyDict_New();
4463 0 : if (cache == NULL)
4464 0 : return NULL;
4465 : }
4466 0 : len = PyLong_FromSsize_t(length);
4467 0 : if (len == NULL)
4468 0 : return NULL;
4469 0 : key = PyTuple_Pack(2, itemtype, len);
4470 0 : Py_DECREF(len);
4471 0 : if (!key)
4472 0 : return NULL;
4473 0 : result = PyDict_GetItemProxy(cache, key);
4474 0 : if (result) {
4475 0 : Py_INCREF(result);
4476 0 : Py_DECREF(key);
4477 0 : return result;
4478 : }
4479 :
4480 0 : if (!PyType_Check(itemtype)) {
4481 0 : PyErr_SetString(PyExc_TypeError,
4482 : "Expected a type object");
4483 0 : Py_DECREF(key);
4484 0 : return NULL;
4485 : }
4486 : #ifdef MS_WIN64
4487 : sprintf(name, "%.200s_Array_%Id",
4488 : ((PyTypeObject *)itemtype)->tp_name, length);
4489 : #else
4490 0 : sprintf(name, "%.200s_Array_%ld",
4491 : ((PyTypeObject *)itemtype)->tp_name, (long)length);
4492 : #endif
4493 :
4494 0 : result = PyObject_CallFunction((PyObject *)&PyCArrayType_Type,
4495 : "s(O){s:n,s:O}",
4496 : name,
4497 : &PyCArray_Type,
4498 : "_length_",
4499 : length,
4500 : "_type_",
4501 : itemtype
4502 : );
4503 0 : if (result == NULL) {
4504 0 : Py_DECREF(key);
4505 0 : return NULL;
4506 : }
4507 0 : if (-1 == PyDict_SetItemProxy(cache, key, result)) {
4508 0 : Py_DECREF(key);
4509 0 : Py_DECREF(result);
4510 0 : return NULL;
4511 : }
4512 0 : Py_DECREF(key);
4513 0 : return result;
4514 : }
4515 :
4516 :
4517 : /******************************************************************/
4518 : /*
4519 : Simple_Type
4520 : */
4521 :
4522 : static int
4523 0 : Simple_set_value(CDataObject *self, PyObject *value)
4524 : {
4525 : PyObject *result;
4526 0 : StgDictObject *dict = PyObject_stgdict((PyObject *)self);
4527 :
4528 0 : if (value == NULL) {
4529 0 : PyErr_SetString(PyExc_TypeError,
4530 : "can't delete attribute");
4531 0 : return -1;
4532 : }
4533 : assert(dict); /* Cannot be NULL for CDataObject instances */
4534 : assert(dict->setfunc);
4535 0 : result = dict->setfunc(self->b_ptr, value, dict->size);
4536 0 : if (!result)
4537 0 : return -1;
4538 :
4539 : /* consumes the refcount the setfunc returns */
4540 0 : return KeepRef(self, 0, result);
4541 : }
4542 :
4543 : static int
4544 0 : Simple_init(CDataObject *self, PyObject *args, PyObject *kw)
4545 : {
4546 0 : PyObject *value = NULL;
4547 0 : if (!PyArg_UnpackTuple(args, "__init__", 0, 1, &value))
4548 0 : return -1;
4549 0 : if (value)
4550 0 : return Simple_set_value(self, value);
4551 0 : return 0;
4552 : }
4553 :
4554 : static PyObject *
4555 0 : Simple_get_value(CDataObject *self)
4556 : {
4557 : StgDictObject *dict;
4558 0 : dict = PyObject_stgdict((PyObject *)self);
4559 : assert(dict); /* Cannot be NULL for CDataObject instances */
4560 : assert(dict->getfunc);
4561 0 : return dict->getfunc(self->b_ptr, self->b_size);
4562 : }
4563 :
4564 : static PyGetSetDef Simple_getsets[] = {
4565 : { "value", (getter)Simple_get_value, (setter)Simple_set_value,
4566 : "current value", NULL },
4567 : { NULL, NULL }
4568 : };
4569 :
4570 : static PyObject *
4571 0 : Simple_from_outparm(PyObject *self, PyObject *args)
4572 : {
4573 0 : if (_ctypes_simple_instance((PyObject *)Py_TYPE(self))) {
4574 0 : Py_INCREF(self);
4575 0 : return self;
4576 : }
4577 : /* call stgdict->getfunc */
4578 0 : return Simple_get_value((CDataObject *)self);
4579 : }
4580 :
4581 : static PyMethodDef Simple_methods[] = {
4582 : { "__ctypes_from_outparam__", Simple_from_outparm, METH_NOARGS, },
4583 : { NULL, NULL },
4584 : };
4585 :
4586 0 : static int Simple_bool(CDataObject *self)
4587 : {
4588 0 : return memcmp(self->b_ptr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", self->b_size);
4589 : }
4590 :
4591 : static PyNumberMethods Simple_as_number = {
4592 : 0, /* nb_add */
4593 : 0, /* nb_subtract */
4594 : 0, /* nb_multiply */
4595 : 0, /* nb_remainder */
4596 : 0, /* nb_divmod */
4597 : 0, /* nb_power */
4598 : 0, /* nb_negative */
4599 : 0, /* nb_positive */
4600 : 0, /* nb_absolute */
4601 : (inquiry)Simple_bool, /* nb_bool */
4602 : };
4603 :
4604 : /* "%s(%s)" % (self.__class__.__name__, self.value) */
4605 : static PyObject *
4606 0 : Simple_repr(CDataObject *self)
4607 : {
4608 : PyObject *val, *result;
4609 :
4610 0 : if (Py_TYPE(self)->tp_base != &Simple_Type) {
4611 0 : return PyUnicode_FromFormat("<%s object at %p>",
4612 0 : Py_TYPE(self)->tp_name, self);
4613 : }
4614 :
4615 0 : val = Simple_get_value(self);
4616 0 : if (val == NULL)
4617 0 : return NULL;
4618 :
4619 0 : result = PyUnicode_FromFormat("%s(%R)",
4620 0 : Py_TYPE(self)->tp_name, val);
4621 0 : Py_DECREF(val);
4622 0 : return result;
4623 : }
4624 :
4625 : static PyTypeObject Simple_Type = {
4626 : PyVarObject_HEAD_INIT(NULL, 0)
4627 : "_ctypes._SimpleCData",
4628 : sizeof(CDataObject), /* tp_basicsize */
4629 : 0, /* tp_itemsize */
4630 : 0, /* tp_dealloc */
4631 : 0, /* tp_print */
4632 : 0, /* tp_getattr */
4633 : 0, /* tp_setattr */
4634 : 0, /* tp_reserved */
4635 : (reprfunc)&Simple_repr, /* tp_repr */
4636 : &Simple_as_number, /* tp_as_number */
4637 : 0, /* tp_as_sequence */
4638 : 0, /* tp_as_mapping */
4639 : 0, /* tp_hash */
4640 : 0, /* tp_call */
4641 : 0, /* tp_str */
4642 : 0, /* tp_getattro */
4643 : 0, /* tp_setattro */
4644 : &PyCData_as_buffer, /* tp_as_buffer */
4645 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
4646 : "XXX to be provided", /* tp_doc */
4647 : (traverseproc)PyCData_traverse, /* tp_traverse */
4648 : (inquiry)PyCData_clear, /* tp_clear */
4649 : 0, /* tp_richcompare */
4650 : 0, /* tp_weaklistoffset */
4651 : 0, /* tp_iter */
4652 : 0, /* tp_iternext */
4653 : Simple_methods, /* tp_methods */
4654 : 0, /* tp_members */
4655 : Simple_getsets, /* tp_getset */
4656 : 0, /* tp_base */
4657 : 0, /* tp_dict */
4658 : 0, /* tp_descr_get */
4659 : 0, /* tp_descr_set */
4660 : 0, /* tp_dictoffset */
4661 : (initproc)Simple_init, /* tp_init */
4662 : 0, /* tp_alloc */
4663 : GenericPyCData_new, /* tp_new */
4664 : 0, /* tp_free */
4665 : };
4666 :
4667 : /******************************************************************/
4668 : /*
4669 : PyCPointer_Type
4670 : */
4671 : static PyObject *
4672 0 : Pointer_item(PyObject *_self, Py_ssize_t index)
4673 : {
4674 0 : CDataObject *self = (CDataObject *)_self;
4675 : Py_ssize_t size;
4676 : Py_ssize_t offset;
4677 : StgDictObject *stgdict, *itemdict;
4678 : PyObject *proto;
4679 :
4680 0 : if (*(void **)self->b_ptr == NULL) {
4681 0 : PyErr_SetString(PyExc_ValueError,
4682 : "NULL pointer access");
4683 0 : return NULL;
4684 : }
4685 :
4686 0 : stgdict = PyObject_stgdict((PyObject *)self);
4687 : assert(stgdict); /* Cannot be NULL for pointer object instances */
4688 :
4689 0 : proto = stgdict->proto;
4690 : assert(proto);
4691 0 : itemdict = PyType_stgdict(proto);
4692 : assert(itemdict); /* proto is the item type of the pointer, a ctypes
4693 : type, so this cannot be NULL */
4694 :
4695 0 : size = itemdict->size;
4696 0 : offset = index * itemdict->size;
4697 :
4698 0 : return PyCData_get(proto, stgdict->getfunc, (PyObject *)self,
4699 0 : index, size, (*(char **)self->b_ptr) + offset);
4700 : }
4701 :
4702 : static int
4703 0 : Pointer_ass_item(PyObject *_self, Py_ssize_t index, PyObject *value)
4704 : {
4705 0 : CDataObject *self = (CDataObject *)_self;
4706 : Py_ssize_t size;
4707 : Py_ssize_t offset;
4708 : StgDictObject *stgdict, *itemdict;
4709 : PyObject *proto;
4710 :
4711 0 : if (value == NULL) {
4712 0 : PyErr_SetString(PyExc_TypeError,
4713 : "Pointer does not support item deletion");
4714 0 : return -1;
4715 : }
4716 :
4717 0 : if (*(void **)self->b_ptr == NULL) {
4718 0 : PyErr_SetString(PyExc_ValueError,
4719 : "NULL pointer access");
4720 0 : return -1;
4721 : }
4722 :
4723 0 : stgdict = PyObject_stgdict((PyObject *)self);
4724 : assert(stgdict); /* Cannot be NULL fr pointer instances */
4725 :
4726 0 : proto = stgdict->proto;
4727 : assert(proto);
4728 :
4729 0 : itemdict = PyType_stgdict(proto);
4730 : assert(itemdict); /* Cannot be NULL because the itemtype of a pointer
4731 : is always a ctypes type */
4732 :
4733 0 : size = itemdict->size;
4734 0 : offset = index * itemdict->size;
4735 :
4736 0 : return PyCData_set((PyObject *)self, proto, stgdict->setfunc, value,
4737 0 : index, size, (*(char **)self->b_ptr) + offset);
4738 : }
4739 :
4740 : static PyObject *
4741 0 : Pointer_get_contents(CDataObject *self, void *closure)
4742 : {
4743 : StgDictObject *stgdict;
4744 :
4745 0 : if (*(void **)self->b_ptr == NULL) {
4746 0 : PyErr_SetString(PyExc_ValueError,
4747 : "NULL pointer access");
4748 0 : return NULL;
4749 : }
4750 :
4751 0 : stgdict = PyObject_stgdict((PyObject *)self);
4752 : assert(stgdict); /* Cannot be NULL fr pointer instances */
4753 0 : return PyCData_FromBaseObj(stgdict->proto,
4754 : (PyObject *)self, 0,
4755 0 : *(void **)self->b_ptr);
4756 : }
4757 :
4758 : static int
4759 0 : Pointer_set_contents(CDataObject *self, PyObject *value, void *closure)
4760 : {
4761 : StgDictObject *stgdict;
4762 : CDataObject *dst;
4763 : PyObject *keep;
4764 :
4765 0 : if (value == NULL) {
4766 0 : PyErr_SetString(PyExc_TypeError,
4767 : "Pointer does not support item deletion");
4768 0 : return -1;
4769 : }
4770 0 : stgdict = PyObject_stgdict((PyObject *)self);
4771 : assert(stgdict); /* Cannot be NULL fr pointer instances */
4772 : assert(stgdict->proto);
4773 0 : if (!CDataObject_Check(value)) {
4774 0 : int res = PyObject_IsInstance(value, stgdict->proto);
4775 0 : if (res == -1)
4776 0 : return -1;
4777 0 : if (!res) {
4778 0 : PyErr_Format(PyExc_TypeError,
4779 : "expected %s instead of %s",
4780 0 : ((PyTypeObject *)(stgdict->proto))->tp_name,
4781 0 : Py_TYPE(value)->tp_name);
4782 0 : return -1;
4783 : }
4784 : }
4785 :
4786 0 : dst = (CDataObject *)value;
4787 0 : *(void **)self->b_ptr = dst->b_ptr;
4788 :
4789 : /*
4790 : A Pointer instance must keep a the value it points to alive. So, a
4791 : pointer instance has b_length set to 2 instead of 1, and we set
4792 : 'value' itself as the second item of the b_objects list, additionally.
4793 : */
4794 0 : Py_INCREF(value);
4795 0 : if (-1 == KeepRef(self, 1, value))
4796 0 : return -1;
4797 :
4798 0 : keep = GetKeepedObjects(dst);
4799 0 : Py_INCREF(keep);
4800 0 : return KeepRef(self, 0, keep);
4801 : }
4802 :
4803 : static PyGetSetDef Pointer_getsets[] = {
4804 : { "contents", (getter)Pointer_get_contents,
4805 : (setter)Pointer_set_contents,
4806 : "the object this pointer points to (read-write)", NULL },
4807 : { NULL, NULL }
4808 : };
4809 :
4810 : static int
4811 0 : Pointer_init(CDataObject *self, PyObject *args, PyObject *kw)
4812 : {
4813 0 : PyObject *value = NULL;
4814 :
4815 0 : if (!PyArg_UnpackTuple(args, "POINTER", 0, 1, &value))
4816 0 : return -1;
4817 0 : if (value == NULL)
4818 0 : return 0;
4819 0 : return Pointer_set_contents(self, value, NULL);
4820 : }
4821 :
4822 : static PyObject *
4823 0 : Pointer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
4824 : {
4825 0 : StgDictObject *dict = PyType_stgdict((PyObject *)type);
4826 0 : if (!dict || !dict->proto) {
4827 0 : PyErr_SetString(PyExc_TypeError,
4828 : "Cannot create instance: has no _type_");
4829 0 : return NULL;
4830 : }
4831 0 : return GenericPyCData_new(type, args, kw);
4832 : }
4833 :
4834 : static PyObject *
4835 0 : Pointer_subscript(PyObject *_self, PyObject *item)
4836 : {
4837 0 : CDataObject *self = (CDataObject *)_self;
4838 0 : if (PyIndex_Check(item)) {
4839 0 : Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
4840 0 : if (i == -1 && PyErr_Occurred())
4841 0 : return NULL;
4842 0 : return Pointer_item(_self, i);
4843 : }
4844 0 : else if (PySlice_Check(item)) {
4845 0 : PySliceObject *slice = (PySliceObject *)item;
4846 : Py_ssize_t start, stop, step;
4847 : PyObject *np;
4848 : StgDictObject *stgdict, *itemdict;
4849 : PyObject *proto;
4850 : Py_ssize_t i, len, cur;
4851 :
4852 : /* Since pointers have no length, and we want to apply
4853 : different semantics to negative indices than normal
4854 : slicing, we have to dissect the slice object ourselves.*/
4855 0 : if (slice->step == Py_None) {
4856 0 : step = 1;
4857 : }
4858 : else {
4859 0 : step = PyNumber_AsSsize_t(slice->step,
4860 : PyExc_ValueError);
4861 0 : if (step == -1 && PyErr_Occurred())
4862 0 : return NULL;
4863 0 : if (step == 0) {
4864 0 : PyErr_SetString(PyExc_ValueError,
4865 : "slice step cannot be zero");
4866 0 : return NULL;
4867 : }
4868 : }
4869 0 : if (slice->start == Py_None) {
4870 0 : if (step < 0) {
4871 0 : PyErr_SetString(PyExc_ValueError,
4872 : "slice start is required "
4873 : "for step < 0");
4874 0 : return NULL;
4875 : }
4876 0 : start = 0;
4877 : }
4878 : else {
4879 0 : start = PyNumber_AsSsize_t(slice->start,
4880 : PyExc_ValueError);
4881 0 : if (start == -1 && PyErr_Occurred())
4882 0 : return NULL;
4883 : }
4884 0 : if (slice->stop == Py_None) {
4885 0 : PyErr_SetString(PyExc_ValueError,
4886 : "slice stop is required");
4887 0 : return NULL;
4888 : }
4889 0 : stop = PyNumber_AsSsize_t(slice->stop,
4890 : PyExc_ValueError);
4891 0 : if (stop == -1 && PyErr_Occurred())
4892 0 : return NULL;
4893 0 : if ((step > 0 && start > stop) ||
4894 0 : (step < 0 && start < stop))
4895 0 : len = 0;
4896 0 : else if (step > 0)
4897 0 : len = (stop - start - 1) / step + 1;
4898 : else
4899 0 : len = (stop - start + 1) / step + 1;
4900 :
4901 0 : stgdict = PyObject_stgdict((PyObject *)self);
4902 : assert(stgdict); /* Cannot be NULL for pointer instances */
4903 0 : proto = stgdict->proto;
4904 : assert(proto);
4905 0 : itemdict = PyType_stgdict(proto);
4906 : assert(itemdict);
4907 0 : if (itemdict->getfunc == _ctypes_get_fielddesc("c")->getfunc) {
4908 0 : char *ptr = *(char **)self->b_ptr;
4909 : char *dest;
4910 :
4911 0 : if (len <= 0)
4912 0 : return PyBytes_FromStringAndSize("", 0);
4913 0 : if (step == 1) {
4914 0 : return PyBytes_FromStringAndSize(ptr + start,
4915 : len);
4916 : }
4917 0 : dest = (char *)PyMem_Malloc(len);
4918 0 : if (dest == NULL)
4919 0 : return PyErr_NoMemory();
4920 0 : for (cur = start, i = 0; i < len; cur += step, i++) {
4921 0 : dest[i] = ptr[cur];
4922 : }
4923 0 : np = PyBytes_FromStringAndSize(dest, len);
4924 0 : PyMem_Free(dest);
4925 0 : return np;
4926 : }
4927 : #ifdef CTYPES_UNICODE
4928 0 : if (itemdict->getfunc == _ctypes_get_fielddesc("u")->getfunc) {
4929 0 : wchar_t *ptr = *(wchar_t **)self->b_ptr;
4930 : wchar_t *dest;
4931 :
4932 0 : if (len <= 0)
4933 0 : return PyUnicode_New(0, 0);
4934 0 : if (step == 1) {
4935 0 : return PyUnicode_FromWideChar(ptr + start,
4936 : len);
4937 : }
4938 0 : dest = (wchar_t *)PyMem_Malloc(len * sizeof(wchar_t));
4939 0 : if (dest == NULL)
4940 0 : return PyErr_NoMemory();
4941 0 : for (cur = start, i = 0; i < len; cur += step, i++) {
4942 0 : dest[i] = ptr[cur];
4943 : }
4944 0 : np = PyUnicode_FromWideChar(dest, len);
4945 0 : PyMem_Free(dest);
4946 0 : return np;
4947 : }
4948 : #endif
4949 :
4950 0 : np = PyList_New(len);
4951 0 : if (np == NULL)
4952 0 : return NULL;
4953 :
4954 0 : for (cur = start, i = 0; i < len; cur += step, i++) {
4955 0 : PyObject *v = Pointer_item(_self, cur);
4956 0 : PyList_SET_ITEM(np, i, v);
4957 : }
4958 0 : return np;
4959 : }
4960 : else {
4961 0 : PyErr_SetString(PyExc_TypeError,
4962 : "Pointer indices must be integer");
4963 0 : return NULL;
4964 : }
4965 : }
4966 :
4967 : static PySequenceMethods Pointer_as_sequence = {
4968 : 0, /* inquiry sq_length; */
4969 : 0, /* binaryfunc sq_concat; */
4970 : 0, /* intargfunc sq_repeat; */
4971 : Pointer_item, /* intargfunc sq_item; */
4972 : 0, /* intintargfunc sq_slice; */
4973 : Pointer_ass_item, /* intobjargproc sq_ass_item; */
4974 : 0, /* intintobjargproc sq_ass_slice; */
4975 : 0, /* objobjproc sq_contains; */
4976 : /* Added in release 2.0 */
4977 : 0, /* binaryfunc sq_inplace_concat; */
4978 : 0, /* intargfunc sq_inplace_repeat; */
4979 : };
4980 :
4981 : static PyMappingMethods Pointer_as_mapping = {
4982 : 0,
4983 : Pointer_subscript,
4984 : };
4985 :
4986 : static int
4987 0 : Pointer_bool(CDataObject *self)
4988 : {
4989 0 : return (*(void **)self->b_ptr != NULL);
4990 : }
4991 :
4992 : static PyNumberMethods Pointer_as_number = {
4993 : 0, /* nb_add */
4994 : 0, /* nb_subtract */
4995 : 0, /* nb_multiply */
4996 : 0, /* nb_remainder */
4997 : 0, /* nb_divmod */
4998 : 0, /* nb_power */
4999 : 0, /* nb_negative */
5000 : 0, /* nb_positive */
5001 : 0, /* nb_absolute */
5002 : (inquiry)Pointer_bool, /* nb_bool */
5003 : };
5004 :
5005 : PyTypeObject PyCPointer_Type = {
5006 : PyVarObject_HEAD_INIT(NULL, 0)
5007 : "_ctypes._Pointer",
5008 : sizeof(CDataObject), /* tp_basicsize */
5009 : 0, /* tp_itemsize */
5010 : 0, /* tp_dealloc */
5011 : 0, /* tp_print */
5012 : 0, /* tp_getattr */
5013 : 0, /* tp_setattr */
5014 : 0, /* tp_reserved */
5015 : 0, /* tp_repr */
5016 : &Pointer_as_number, /* tp_as_number */
5017 : &Pointer_as_sequence, /* tp_as_sequence */
5018 : &Pointer_as_mapping, /* tp_as_mapping */
5019 : 0, /* tp_hash */
5020 : 0, /* tp_call */
5021 : 0, /* tp_str */
5022 : 0, /* tp_getattro */
5023 : 0, /* tp_setattro */
5024 : &PyCData_as_buffer, /* tp_as_buffer */
5025 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
5026 : "XXX to be provided", /* tp_doc */
5027 : (traverseproc)PyCData_traverse, /* tp_traverse */
5028 : (inquiry)PyCData_clear, /* tp_clear */
5029 : 0, /* tp_richcompare */
5030 : 0, /* tp_weaklistoffset */
5031 : 0, /* tp_iter */
5032 : 0, /* tp_iternext */
5033 : 0, /* tp_methods */
5034 : 0, /* tp_members */
5035 : Pointer_getsets, /* tp_getset */
5036 : 0, /* tp_base */
5037 : 0, /* tp_dict */
5038 : 0, /* tp_descr_get */
5039 : 0, /* tp_descr_set */
5040 : 0, /* tp_dictoffset */
5041 : (initproc)Pointer_init, /* tp_init */
5042 : 0, /* tp_alloc */
5043 : Pointer_new, /* tp_new */
5044 : 0, /* tp_free */
5045 : };
5046 :
5047 :
5048 : /******************************************************************/
5049 : /*
5050 : * Module initialization.
5051 : */
5052 :
5053 : static const char module_docs[] =
5054 : "Create and manipulate C compatible data types in Python.";
5055 :
5056 : #ifdef MS_WIN32
5057 :
5058 : static char comerror_doc[] = "Raised when a COM method call failed.";
5059 :
5060 : int
5061 : comerror_init(PyObject *self, PyObject *args, PyObject *kwds)
5062 : {
5063 : PyObject *hresult, *text, *details;
5064 : PyBaseExceptionObject *bself;
5065 : PyObject *a;
5066 : int status;
5067 :
5068 : if (!_PyArg_NoKeywords(Py_TYPE(self)->tp_name, kwds))
5069 : return -1;
5070 :
5071 : if (!PyArg_ParseTuple(args, "OOO:COMError", &hresult, &text, &details))
5072 : return -1;
5073 :
5074 : a = PySequence_GetSlice(args, 1, PySequence_Size(args));
5075 : if (!a)
5076 : return -1;
5077 : status = PyObject_SetAttrString(self, "args", a);
5078 : Py_DECREF(a);
5079 : if (status < 0)
5080 : return -1;
5081 :
5082 : if (PyObject_SetAttrString(self, "hresult", hresult) < 0)
5083 : return -1;
5084 :
5085 : if (PyObject_SetAttrString(self, "text", text) < 0)
5086 : return -1;
5087 :
5088 : if (PyObject_SetAttrString(self, "details", details) < 0)
5089 : return -1;
5090 :
5091 : bself = (PyBaseExceptionObject *)self;
5092 : Py_DECREF(bself->args);
5093 : bself->args = args;
5094 : Py_INCREF(bself->args);
5095 :
5096 : return 0;
5097 : }
5098 :
5099 : static PyTypeObject PyComError_Type = {
5100 : PyVarObject_HEAD_INIT(NULL, 0)
5101 : "_ctypes.COMError", /* tp_name */
5102 : sizeof(PyBaseExceptionObject), /* tp_basicsize */
5103 : 0, /* tp_itemsize */
5104 : 0, /* tp_dealloc */
5105 : 0, /* tp_print */
5106 : 0, /* tp_getattr */
5107 : 0, /* tp_setattr */
5108 : 0, /* tp_reserved */
5109 : 0, /* tp_repr */
5110 : 0, /* tp_as_number */
5111 : 0, /* tp_as_sequence */
5112 : 0, /* tp_as_mapping */
5113 : 0, /* tp_hash */
5114 : 0, /* tp_call */
5115 : 0, /* tp_str */
5116 : 0, /* tp_getattro */
5117 : 0, /* tp_setattro */
5118 : 0, /* tp_as_buffer */
5119 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
5120 : PyDoc_STR(comerror_doc), /* tp_doc */
5121 : 0, /* tp_traverse */
5122 : 0, /* tp_clear */
5123 : 0, /* tp_richcompare */
5124 : 0, /* tp_weaklistoffset */
5125 : 0, /* tp_iter */
5126 : 0, /* tp_iternext */
5127 : 0, /* tp_methods */
5128 : 0, /* tp_members */
5129 : 0, /* tp_getset */
5130 : 0, /* tp_base */
5131 : 0, /* tp_dict */
5132 : 0, /* tp_descr_get */
5133 : 0, /* tp_descr_set */
5134 : 0, /* tp_dictoffset */
5135 : (initproc)comerror_init, /* tp_init */
5136 : 0, /* tp_alloc */
5137 : 0, /* tp_new */
5138 : };
5139 :
5140 :
5141 : static int
5142 : create_comerror(void)
5143 : {
5144 : PyComError_Type.tp_base = (PyTypeObject*)PyExc_Exception;
5145 : if (PyType_Ready(&PyComError_Type) < 0)
5146 : return -1;
5147 : Py_INCREF(&PyComError_Type);
5148 : ComError = (PyObject*)&PyComError_Type;
5149 : return 0;
5150 : }
5151 :
5152 : #endif
5153 :
5154 : static PyObject *
5155 0 : string_at(const char *ptr, int size)
5156 : {
5157 0 : if (size == -1)
5158 0 : return PyBytes_FromStringAndSize(ptr, strlen(ptr));
5159 0 : return PyBytes_FromStringAndSize(ptr, size);
5160 : }
5161 :
5162 : static int
5163 0 : cast_check_pointertype(PyObject *arg)
5164 : {
5165 : StgDictObject *dict;
5166 :
5167 0 : if (PyCPointerTypeObject_Check(arg))
5168 0 : return 1;
5169 0 : if (PyCFuncPtrTypeObject_Check(arg))
5170 0 : return 1;
5171 0 : dict = PyType_stgdict(arg);
5172 0 : if (dict) {
5173 0 : if (PyUnicode_Check(dict->proto)
5174 0 : && (strchr("sPzUZXO", _PyUnicode_AsString(dict->proto)[0]))) {
5175 : /* simple pointer types, c_void_p, c_wchar_p, BSTR, ... */
5176 0 : return 1;
5177 : }
5178 : }
5179 0 : PyErr_Format(PyExc_TypeError,
5180 : "cast() argument 2 must be a pointer type, not %s",
5181 0 : PyType_Check(arg)
5182 : ? ((PyTypeObject *)arg)->tp_name
5183 0 : : Py_TYPE(arg)->tp_name);
5184 0 : return 0;
5185 : }
5186 :
5187 : static PyObject *
5188 0 : cast(void *ptr, PyObject *src, PyObject *ctype)
5189 : {
5190 : CDataObject *result;
5191 0 : if (0 == cast_check_pointertype(ctype))
5192 0 : return NULL;
5193 0 : result = (CDataObject *)PyObject_CallFunctionObjArgs(ctype, NULL);
5194 0 : if (result == NULL)
5195 0 : return NULL;
5196 :
5197 : /*
5198 : The casted objects '_objects' member:
5199 :
5200 : It must certainly contain the source objects one.
5201 : It must contain the source object itself.
5202 : */
5203 0 : if (CDataObject_Check(src)) {
5204 0 : CDataObject *obj = (CDataObject *)src;
5205 : /* PyCData_GetContainer will initialize src.b_objects, we need
5206 : this so it can be shared */
5207 0 : PyCData_GetContainer(obj);
5208 : /* But we need a dictionary! */
5209 0 : if (obj->b_objects == Py_None) {
5210 0 : Py_DECREF(Py_None);
5211 0 : obj->b_objects = PyDict_New();
5212 0 : if (obj->b_objects == NULL)
5213 0 : goto failed;
5214 : }
5215 0 : Py_XINCREF(obj->b_objects);
5216 0 : result->b_objects = obj->b_objects;
5217 0 : if (result->b_objects && PyDict_CheckExact(result->b_objects)) {
5218 : PyObject *index;
5219 : int rc;
5220 0 : index = PyLong_FromVoidPtr((void *)src);
5221 0 : if (index == NULL)
5222 0 : goto failed;
5223 0 : rc = PyDict_SetItem(result->b_objects, index, src);
5224 0 : Py_DECREF(index);
5225 0 : if (rc == -1)
5226 0 : goto failed;
5227 : }
5228 : }
5229 : /* Should we assert that result is a pointer type? */
5230 0 : memcpy(result->b_ptr, &ptr, sizeof(void *));
5231 0 : return (PyObject *)result;
5232 :
5233 : failed:
5234 0 : Py_DECREF(result);
5235 0 : return NULL;
5236 : }
5237 :
5238 : #ifdef CTYPES_UNICODE
5239 : static PyObject *
5240 0 : wstring_at(const wchar_t *ptr, int size)
5241 : {
5242 0 : Py_ssize_t ssize = size;
5243 0 : if (ssize == -1)
5244 0 : ssize = wcslen(ptr);
5245 0 : return PyUnicode_FromWideChar(ptr, ssize);
5246 : }
5247 : #endif
5248 :
5249 :
5250 : static struct PyModuleDef _ctypesmodule = {
5251 : PyModuleDef_HEAD_INIT,
5252 : "_ctypes",
5253 : module_docs,
5254 : -1,
5255 : _ctypes_module_methods,
5256 : NULL,
5257 : NULL,
5258 : NULL,
5259 : NULL
5260 : };
5261 :
5262 : PyMODINIT_FUNC
5263 0 : PyInit__ctypes(void)
5264 : {
5265 : PyObject *m;
5266 :
5267 : /* Note:
5268 : ob_type is the metatype (the 'type'), defaults to PyType_Type,
5269 : tp_base is the base type, defaults to 'object' aka PyBaseObject_Type.
5270 : */
5271 : #ifdef WITH_THREAD
5272 0 : PyEval_InitThreads();
5273 : #endif
5274 0 : m = PyModule_Create(&_ctypesmodule);
5275 0 : if (!m)
5276 0 : return NULL;
5277 :
5278 0 : _ctypes_ptrtype_cache = PyDict_New();
5279 0 : if (_ctypes_ptrtype_cache == NULL)
5280 0 : return NULL;
5281 :
5282 0 : PyModule_AddObject(m, "_pointer_type_cache", (PyObject *)_ctypes_ptrtype_cache);
5283 :
5284 0 : _unpickle = PyObject_GetAttrString(m, "_unpickle");
5285 0 : if (_unpickle == NULL)
5286 0 : return NULL;
5287 :
5288 0 : if (PyType_Ready(&PyCArg_Type) < 0)
5289 0 : return NULL;
5290 :
5291 0 : if (PyType_Ready(&PyCThunk_Type) < 0)
5292 0 : return NULL;
5293 :
5294 : /* StgDict is derived from PyDict_Type */
5295 0 : PyCStgDict_Type.tp_base = &PyDict_Type;
5296 0 : if (PyType_Ready(&PyCStgDict_Type) < 0)
5297 0 : return NULL;
5298 :
5299 : /*************************************************
5300 : *
5301 : * Metaclasses
5302 : */
5303 :
5304 0 : PyCStructType_Type.tp_base = &PyType_Type;
5305 0 : if (PyType_Ready(&PyCStructType_Type) < 0)
5306 0 : return NULL;
5307 :
5308 0 : UnionType_Type.tp_base = &PyType_Type;
5309 0 : if (PyType_Ready(&UnionType_Type) < 0)
5310 0 : return NULL;
5311 :
5312 0 : PyCPointerType_Type.tp_base = &PyType_Type;
5313 0 : if (PyType_Ready(&PyCPointerType_Type) < 0)
5314 0 : return NULL;
5315 :
5316 0 : PyCArrayType_Type.tp_base = &PyType_Type;
5317 0 : if (PyType_Ready(&PyCArrayType_Type) < 0)
5318 0 : return NULL;
5319 :
5320 0 : PyCSimpleType_Type.tp_base = &PyType_Type;
5321 0 : if (PyType_Ready(&PyCSimpleType_Type) < 0)
5322 0 : return NULL;
5323 :
5324 0 : PyCFuncPtrType_Type.tp_base = &PyType_Type;
5325 0 : if (PyType_Ready(&PyCFuncPtrType_Type) < 0)
5326 0 : return NULL;
5327 :
5328 : /*************************************************
5329 : *
5330 : * Classes using a custom metaclass
5331 : */
5332 :
5333 0 : if (PyType_Ready(&PyCData_Type) < 0)
5334 0 : return NULL;
5335 :
5336 0 : Py_TYPE(&Struct_Type) = &PyCStructType_Type;
5337 0 : Struct_Type.tp_base = &PyCData_Type;
5338 0 : if (PyType_Ready(&Struct_Type) < 0)
5339 0 : return NULL;
5340 0 : Py_INCREF(&Struct_Type);
5341 0 : PyModule_AddObject(m, "Structure", (PyObject *)&Struct_Type);
5342 :
5343 0 : Py_TYPE(&Union_Type) = &UnionType_Type;
5344 0 : Union_Type.tp_base = &PyCData_Type;
5345 0 : if (PyType_Ready(&Union_Type) < 0)
5346 0 : return NULL;
5347 0 : Py_INCREF(&Union_Type);
5348 0 : PyModule_AddObject(m, "Union", (PyObject *)&Union_Type);
5349 :
5350 0 : Py_TYPE(&PyCPointer_Type) = &PyCPointerType_Type;
5351 0 : PyCPointer_Type.tp_base = &PyCData_Type;
5352 0 : if (PyType_Ready(&PyCPointer_Type) < 0)
5353 0 : return NULL;
5354 0 : Py_INCREF(&PyCPointer_Type);
5355 0 : PyModule_AddObject(m, "_Pointer", (PyObject *)&PyCPointer_Type);
5356 :
5357 0 : Py_TYPE(&PyCArray_Type) = &PyCArrayType_Type;
5358 0 : PyCArray_Type.tp_base = &PyCData_Type;
5359 0 : if (PyType_Ready(&PyCArray_Type) < 0)
5360 0 : return NULL;
5361 0 : Py_INCREF(&PyCArray_Type);
5362 0 : PyModule_AddObject(m, "Array", (PyObject *)&PyCArray_Type);
5363 :
5364 0 : Py_TYPE(&Simple_Type) = &PyCSimpleType_Type;
5365 0 : Simple_Type.tp_base = &PyCData_Type;
5366 0 : if (PyType_Ready(&Simple_Type) < 0)
5367 0 : return NULL;
5368 0 : Py_INCREF(&Simple_Type);
5369 0 : PyModule_AddObject(m, "_SimpleCData", (PyObject *)&Simple_Type);
5370 :
5371 0 : Py_TYPE(&PyCFuncPtr_Type) = &PyCFuncPtrType_Type;
5372 0 : PyCFuncPtr_Type.tp_base = &PyCData_Type;
5373 0 : if (PyType_Ready(&PyCFuncPtr_Type) < 0)
5374 0 : return NULL;
5375 0 : Py_INCREF(&PyCFuncPtr_Type);
5376 0 : PyModule_AddObject(m, "CFuncPtr", (PyObject *)&PyCFuncPtr_Type);
5377 :
5378 : /*************************************************
5379 : *
5380 : * Simple classes
5381 : */
5382 :
5383 : /* PyCField_Type is derived from PyBaseObject_Type */
5384 0 : if (PyType_Ready(&PyCField_Type) < 0)
5385 0 : return NULL;
5386 :
5387 : /*************************************************
5388 : *
5389 : * Other stuff
5390 : */
5391 :
5392 0 : DictRemover_Type.tp_new = PyType_GenericNew;
5393 0 : if (PyType_Ready(&DictRemover_Type) < 0)
5394 0 : return NULL;
5395 :
5396 : #ifdef MS_WIN32
5397 : if (create_comerror() < 0)
5398 : return NULL;
5399 : PyModule_AddObject(m, "COMError", ComError);
5400 :
5401 : PyModule_AddObject(m, "FUNCFLAG_HRESULT", PyLong_FromLong(FUNCFLAG_HRESULT));
5402 : PyModule_AddObject(m, "FUNCFLAG_STDCALL", PyLong_FromLong(FUNCFLAG_STDCALL));
5403 : #endif
5404 0 : PyModule_AddObject(m, "FUNCFLAG_CDECL", PyLong_FromLong(FUNCFLAG_CDECL));
5405 0 : PyModule_AddObject(m, "FUNCFLAG_USE_ERRNO", PyLong_FromLong(FUNCFLAG_USE_ERRNO));
5406 0 : PyModule_AddObject(m, "FUNCFLAG_USE_LASTERROR", PyLong_FromLong(FUNCFLAG_USE_LASTERROR));
5407 0 : PyModule_AddObject(m, "FUNCFLAG_PYTHONAPI", PyLong_FromLong(FUNCFLAG_PYTHONAPI));
5408 0 : PyModule_AddStringConstant(m, "__version__", "1.1.0");
5409 :
5410 0 : PyModule_AddObject(m, "_memmove_addr", PyLong_FromVoidPtr(memmove));
5411 0 : PyModule_AddObject(m, "_memset_addr", PyLong_FromVoidPtr(memset));
5412 0 : PyModule_AddObject(m, "_string_at_addr", PyLong_FromVoidPtr(string_at));
5413 0 : PyModule_AddObject(m, "_cast_addr", PyLong_FromVoidPtr(cast));
5414 : #ifdef CTYPES_UNICODE
5415 0 : PyModule_AddObject(m, "_wstring_at_addr", PyLong_FromVoidPtr(wstring_at));
5416 : #endif
5417 :
5418 : /* If RTLD_LOCAL is not defined (Windows!), set it to zero. */
5419 : #ifndef RTLD_LOCAL
5420 : #define RTLD_LOCAL 0
5421 : #endif
5422 :
5423 : /* If RTLD_GLOBAL is not defined (cygwin), set it to the same value as
5424 : RTLD_LOCAL.
5425 : */
5426 : #ifndef RTLD_GLOBAL
5427 : #define RTLD_GLOBAL RTLD_LOCAL
5428 : #endif
5429 :
5430 0 : PyModule_AddObject(m, "RTLD_LOCAL", PyLong_FromLong(RTLD_LOCAL));
5431 0 : PyModule_AddObject(m, "RTLD_GLOBAL", PyLong_FromLong(RTLD_GLOBAL));
5432 :
5433 0 : PyExc_ArgError = PyErr_NewException("ctypes.ArgumentError", NULL, NULL);
5434 0 : if (PyExc_ArgError) {
5435 0 : Py_INCREF(PyExc_ArgError);
5436 0 : PyModule_AddObject(m, "ArgumentError", PyExc_ArgError);
5437 : }
5438 0 : return m;
5439 : }
5440 :
5441 : /*
5442 : Local Variables:
5443 : compile-command: "cd .. && python setup.py -q build -g && python setup.py -q build install --home ~"
5444 : End:
5445 : */
|