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