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