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