LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/python3/Modules/_ctypes - _ctypes.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 2074 0.0 %
Date: 2012-12-17 Functions: 0 113 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10