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