summaryrefslogtreecommitdiffstats
path: root/siplib
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2011-11-22 02:59:34 -0600
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2011-11-22 02:59:34 -0600
commit6c4cc3653e8dd7668295f3e659b7eb4dc571b67c (patch)
treea559fd71fc982e35a4f984d85a5c9d92b764ae8c /siplib
downloadsip4-tqt-6c4cc3653e8dd7668295f3e659b7eb4dc571b67c.tar.gz
sip4-tqt-6c4cc3653e8dd7668295f3e659b7eb4dc571b67c.zip
Initial import of SIP4 for Qt3
Diffstat (limited to 'siplib')
-rw-r--r--siplib/apiversions.c295
-rw-r--r--siplib/bool.cpp22
-rw-r--r--siplib/descriptors.c305
-rw-r--r--siplib/objmap.c282
-rw-r--r--siplib/qtlib.c659
-rw-r--r--siplib/sip.h1587
-rw-r--r--siplib/sipint.h149
-rw-r--r--siplib/siplib.c10501
-rw-r--r--siplib/siplib.sbf19
-rw-r--r--siplib/threads.c226
-rw-r--r--siplib/voidptr.c579
11 files changed, 14624 insertions, 0 deletions
diff --git a/siplib/apiversions.c b/siplib/apiversions.c
new file mode 100644
index 0000000..7d86c76
--- /dev/null
+++ b/siplib/apiversions.c
@@ -0,0 +1,295 @@
+/*
+ * The implementation of the supprt for setting API versions.
+ *
+ * Copyright (c) 2010 Riverbank Computing Limited <info@riverbankcomputing.com>
+ *
+ * This file is part of SIP.
+ *
+ * This copy of SIP is licensed for use under the terms of the SIP License
+ * Agreement. See the file LICENSE for more details.
+ *
+ * This copy of SIP may also used under the terms of the GNU General Public
+ * License v2 or v3 as published by the Free Software Foundation which can be
+ * found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package.
+ *
+ * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+#include <Python.h>
+
+#include <string.h>
+
+#include "sip.h"
+#include "sipint.h"
+
+
+/*
+ * The structure that defines the version number of an API.
+ */
+typedef struct _apiVersionDef {
+ /* The name of the API. */
+ const char *api_name;
+
+ /*
+ * The version number of the API. This will either be set explicitly via
+ * a call to sip.setapi() or implicitly by an imported module.
+ */
+ int version_nr;
+
+ /* The next in the list of APIs. */
+ struct _apiVersionDef *next;
+} apiVersionDef;
+
+
+/*
+ * The list of API versions.
+ */
+static apiVersionDef *api_versions = NULL;
+
+
+/*
+ * Forward declarations.
+ */
+static int add_api(const char *api, int version_nr);
+static apiVersionDef *find_api(const char *api);
+
+
+/*
+ * See if a range of versions of a particular API is enabled.
+ */
+int sip_api_is_api_enabled(const char *name, int from, int to)
+{
+ const apiVersionDef *avd;
+
+ if ((avd = find_api(name)) == NULL)
+ return FALSE;
+
+ if (from > 0 && avd->version_nr < from)
+ return FALSE;
+
+ if (to > 0 && avd->version_nr >= to)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/*
+ * Initialise the the API for a module and return a negative value on error.
+ */
+int sipInitAPI(sipExportedModuleDef *em, PyObject *mod_dict)
+{
+ int *apis, i;
+ sipVersionedFunctionDef *vf;
+ sipTypeDef **tdp;
+
+ /* See if the module defines any APIs. */
+ if ((apis = em->em_versions) != NULL)
+ {
+ while (apis[0] >= 0)
+ {
+ /*
+ * See if it is an API definition rather than a range
+ * definition.
+ */
+ if (apis[2] < 0)
+ {
+ const char *api_name;
+ const apiVersionDef *avd;
+
+ api_name = sipNameFromPool(em, apis[0]);
+
+ /* Use the default version if not already set explicitly. */
+ if ((avd = find_api(api_name)) == NULL)
+ if (add_api(api_name, apis[1]) < 0)
+ return -1;
+ }
+
+ apis += 3;
+ }
+ }
+
+ /* Add any versioned global functions to the module dictionary. */
+ if ((vf = em->em_versioned_functions) != NULL)
+ {
+ while (vf->vf_name >= 0)
+ {
+ if (sipIsRangeEnabled(em, vf->vf_api_range))
+ {
+ const char *func_name = sipNameFromPool(em, vf->vf_name);
+ PyMethodDef *pmd;
+ PyObject *py_func;
+
+ if ((pmd = sip_api_malloc(sizeof (PyMethodDef))) == NULL)
+ return -1;
+
+ pmd->ml_name = SIP_MLNAME_CAST(func_name);
+ pmd->ml_meth = vf->vf_function;
+ pmd->ml_flags = vf->vf_flags;
+ pmd->ml_doc = vf->vf_docstring;
+
+ if ((py_func = PyCFunction_New(pmd, NULL)) == NULL)
+ return -1;
+
+ if (PyDict_SetItemString(mod_dict, func_name, py_func) < 0)
+ {
+ Py_DECREF(py_func);
+ return -1;
+ }
+
+ Py_DECREF(py_func);
+ }
+
+ ++vf;
+ }
+ }
+
+ /* Update the types table according to any version information. */
+ for (tdp = em->em_types, i = 0; i < em->em_nrtypes; ++i, ++tdp)
+ {
+ sipTypeDef *td;
+
+ if ((td = *tdp) != NULL && td->td_version >= 0)
+ {
+ do
+ {
+ if (sipIsRangeEnabled(em, td->td_version))
+ {
+ /* Update the type with the enabled version. */
+ *tdp = td;
+ break;
+ }
+ }
+ while ((td = td->td_next_version) != NULL);
+
+ /*
+ * If there is no enabled version then stub the disabled version
+ * so that we don't lose the name from the (sorted) types table.
+ */
+ if (td == NULL)
+ sipTypeSetStub(*tdp);
+ }
+ }
+
+ return 0;
+}
+
+
+/*
+ * Get the version number for an API.
+ */
+PyObject *sipGetAPI(PyObject *self, PyObject *args)
+{
+ const char *api;
+ const apiVersionDef *avd;
+
+ if (!PyArg_ParseTuple(args, "s:getapi", &api))
+ return NULL;
+
+ if ((avd = find_api(api)) == NULL)
+ {
+ PyErr_Format(PyExc_ValueError, "unknown API '%s'", api);
+ return NULL;
+ }
+
+#if PY_MAJOR_VERSION >= 3
+ return PyLong_FromLong(avd->version_nr);
+#else
+ return PyInt_FromLong(avd->version_nr);
+#endif
+}
+
+
+/*
+ * Set the version number for an API.
+ */
+PyObject *sipSetAPI(PyObject *self, PyObject *args)
+{
+ const char *api;
+ int version_nr;
+ const apiVersionDef *avd;
+
+ if (!PyArg_ParseTuple(args, "si:setapi", &api, &version_nr))
+ return NULL;
+
+ if (version_nr < 1)
+ {
+ PyErr_Format(PyExc_ValueError,
+ "API version numbers must be greater or equal to 1, not %d",
+ version_nr);
+ return NULL;
+ }
+
+ if ((avd = find_api(api)) == NULL)
+ {
+ char *api_copy;
+
+ /* Make a deep copy of the name. */
+ if ((api_copy = sip_api_malloc(strlen(api) + 1)) == NULL)
+ return NULL;
+
+ strcpy(api_copy, api);
+
+ if (add_api(api_copy, version_nr) < 0)
+ return NULL;
+ }
+ else if (avd->version_nr != version_nr)
+ {
+ PyErr_Format(PyExc_ValueError,
+ "API '%s' has already been set to version %d", api,
+ avd->version_nr);
+ return NULL;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+/*
+ * Add a new API to the global list returning a negative value on error.
+ */
+static int add_api(const char *api, int version_nr)
+{
+ apiVersionDef *avd;
+
+ if ((avd = sip_api_malloc(sizeof (apiVersionDef))) == NULL)
+ return -1;
+
+ avd->api_name = api;
+ avd->version_nr = version_nr;
+ avd->next = api_versions;
+
+ api_versions = avd;
+
+ return 0;
+}
+
+
+/*
+ * Return the definition for the given API, or NULL if there was none.
+ */
+static apiVersionDef *find_api(const char *api)
+{
+ apiVersionDef *avd;
+
+ for (avd = api_versions; avd != NULL; avd = avd->next)
+ if (strcmp(avd->api_name, api) == 0)
+ break;
+
+ return avd;
+}
+
+
+/*
+ * Return TRUE if a range defined by a range index is enabled.
+ */
+int sipIsRangeEnabled(sipExportedModuleDef *em, int range_index)
+{
+ int *range = &em->em_versions[range_index * 3];
+ const char *api_name = sipNameFromPool(em, range[0]);
+
+ return sip_api_is_api_enabled(api_name, range[1], range[2]);
+}
diff --git a/siplib/bool.cpp b/siplib/bool.cpp
new file mode 100644
index 0000000..8936287
--- /dev/null
+++ b/siplib/bool.cpp
@@ -0,0 +1,22 @@
+// This contains all the C++ code that is needed by the sip module.
+//
+// Copyright (c) 2010 Riverbank Computing Limited <info@riverbankcomputing.com>
+//
+// This file is part of SIP.
+//
+// This copy of SIP is licensed for use under the terms of the SIP License
+// Agreement. See the file LICENSE for more details.
+//
+// This copy of SIP may also used under the terms of the GNU General Public
+// License v2 or v3 as published by the Free Software Foundation which can be
+// found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package.
+//
+// SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+
+// Set a C++ bool for the main C implementation of the module.
+extern "C" void sipSetBool(void *ptr, int val)
+{
+ *reinterpret_cast<bool *>(ptr) = val;
+}
diff --git a/siplib/descriptors.c b/siplib/descriptors.c
new file mode 100644
index 0000000..29277c5
--- /dev/null
+++ b/siplib/descriptors.c
@@ -0,0 +1,305 @@
+/*
+ * The implementation of the different descriptors.
+ *
+ * Copyright (c) 2010 Riverbank Computing Limited <info@riverbankcomputing.com>
+ *
+ * This file is part of SIP.
+ *
+ * This copy of SIP is licensed for use under the terms of the SIP License
+ * Agreement. See the file LICENSE for more details.
+ *
+ * This copy of SIP may also used under the terms of the GNU General Public
+ * License v2 or v3 as published by the Free Software Foundation which can be
+ * found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package.
+ *
+ * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+#include <Python.h>
+
+#include "sip.h"
+#include "sipint.h"
+
+
+/*****************************************************************************
+ * A method descriptor. We don't use the similar Python descriptor because it
+ * doesn't support a method having static and non-static overloads.
+ *****************************************************************************/
+
+
+/* Forward declarations of slots. */
+static PyObject *sipMethodDescr_descr_get(PyObject *self, PyObject *obj,
+ PyObject *type);
+static PyObject *sipMethodDescr_repr(PyObject *self);
+
+
+/*
+ * The object data structure.
+ */
+typedef struct _sipMethodDescr {
+ PyObject_HEAD
+
+ /* The method definition. */
+ PyMethodDef *pmd;
+} sipMethodDescr;
+
+
+/*
+ * The type data structure.
+ */
+PyTypeObject sipMethodDescr_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "sip.methoddescriptor", /* tp_name */
+ sizeof (sipMethodDescr), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ sipMethodDescr_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ sipMethodDescr_descr_get, /* tp_descr_get */
+};
+
+
+/*
+ * Return a new method descriptor for the given method.
+ */
+PyObject *sipMethodDescr_New(PyMethodDef *pmd)
+{
+ PyObject *descr = PyType_GenericAlloc(&sipMethodDescr_Type, 0);
+
+ if (descr != NULL)
+ ((sipMethodDescr *)descr)->pmd = pmd;
+
+ return descr;
+}
+
+
+/*
+ * The descriptor's descriptor get slot.
+ */
+static PyObject *sipMethodDescr_descr_get(PyObject *self, PyObject *obj,
+ PyObject *type)
+{
+ sipMethodDescr *md = (sipMethodDescr *)self;
+
+ if (obj == Py_None)
+ obj = NULL;
+
+ return PyCFunction_New(md->pmd, obj);
+}
+
+
+/*
+ * The descriptor's repr slot. This is for the benefit of cProfile which seems
+ * to determine attribute names differently to the rest of Python.
+ */
+static PyObject *sipMethodDescr_repr(PyObject *self)
+{
+ sipMethodDescr *md = (sipMethodDescr *)self;
+
+ return
+#if PY_MAJOR_VERSION >= 3
+ PyUnicode_FromFormat
+#else
+ PyString_FromFormat
+#endif
+ ("<built-in method %s>", md->pmd->ml_name);
+}
+
+
+/*****************************************************************************
+ * A variable descriptor. We don't use the similar Python descriptor because
+ * it doesn't support static variables.
+ *****************************************************************************/
+
+
+/* Forward declarations of slots. */
+static PyObject *sipVariableDescr_descr_get(PyObject *self, PyObject *obj,
+ PyObject *type);
+static int sipVariableDescr_descr_set(PyObject *self, PyObject *obj,
+ PyObject *value);
+
+
+/*
+ * The object data structure.
+ */
+typedef struct _sipVariableDescr {
+ PyObject_HEAD
+
+ /* The getter/setter definition. */
+ sipVariableDef *vd;
+
+ /* The generated type definition. */
+ const sipTypeDef *td;
+
+ /* The generated container definition. */
+ const sipContainerDef *cod;
+} sipVariableDescr;
+
+
+/*
+ * The type data structure.
+ */
+PyTypeObject sipVariableDescr_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "sip.variabledescriptor", /* tp_name */
+ sizeof (sipVariableDescr), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ sipVariableDescr_descr_get, /* tp_descr_get */
+ sipVariableDescr_descr_set, /* tp_descr_set */
+};
+
+
+/* Forward declarations. */
+static int get_instance_address(sipVariableDescr *vd, PyObject *obj,
+ void **addrp);
+
+
+/*
+ * Return a new method descriptor for the given getter/setter.
+ */
+PyObject *sipVariableDescr_New(sipVariableDef *vd, const sipTypeDef *td,
+ const sipContainerDef *cod)
+{
+ PyObject *descr = PyType_GenericAlloc(&sipVariableDescr_Type, 0);
+
+ if (descr != NULL)
+ {
+ ((sipVariableDescr *)descr)->vd = vd;
+ ((sipVariableDescr *)descr)->td = td;
+ ((sipVariableDescr *)descr)->cod = cod;
+ }
+
+ return descr;
+}
+
+
+/*
+ * The descriptor's descriptor get slot.
+ */
+static PyObject *sipVariableDescr_descr_get(PyObject *self, PyObject *obj,
+ PyObject *type)
+{
+ sipVariableDescr *vd = (sipVariableDescr *)self;
+ void *addr;
+
+ if (get_instance_address(vd, obj, &addr) < 0)
+ return NULL;
+
+ return vd->vd->vd_getter(addr, type);
+}
+
+
+/*
+ * The descriptor's descriptor set slot.
+ */
+static int sipVariableDescr_descr_set(PyObject *self, PyObject *obj,
+ PyObject *value)
+{
+ sipVariableDescr *vd = (sipVariableDescr *)self;
+ void *addr;
+
+ /* Check that the value isn't const. */
+ if (vd->vd->vd_setter == NULL)
+ {
+ PyErr_Format(PyExc_AttributeError,
+ "'%s' object attribute '%s' is read-only",
+ sipPyNameOfContainer(vd->cod, vd->td), vd->vd->vd_name);
+
+ return -1;
+ }
+
+ if (get_instance_address(vd, obj, &addr) < 0)
+ return -1;
+
+ return vd->vd->vd_setter(addr, value, obj);
+}
+
+
+/*
+ * Return the C/C++ address of any instance.
+ */
+static int get_instance_address(sipVariableDescr *vd, PyObject *obj,
+ void **addrp)
+{
+ void *addr;
+
+ if (vd->vd->vd_is_static)
+ {
+ addr = NULL;
+ }
+ else
+ {
+ /* Check that access was via an instance. */
+ if (obj == NULL || obj == Py_None)
+ {
+ PyErr_Format(PyExc_AttributeError,
+ "'%s' object attribute '%s' is an instance attribute",
+ sipPyNameOfContainer(vd->cod, vd->td), vd->vd->vd_name);
+
+ return -1;
+ }
+
+ /* Get the C++ instance. */
+ if ((addr = sip_api_get_cpp_ptr((sipSimpleWrapper *)obj, vd->td)) == NULL)
+ return -1;
+ }
+
+ *addrp = addr;
+
+ return 0;
+}
diff --git a/siplib/objmap.c b/siplib/objmap.c
new file mode 100644
index 0000000..f9c196d
--- /dev/null
+++ b/siplib/objmap.c
@@ -0,0 +1,282 @@
+/*
+ * This module implements a hash table class for mapping C/C++ addresses to the
+ * corresponding wrapped Python object.
+ *
+ * Copyright (c) 2010 Riverbank Computing Limited <info@riverbankcomputing.com>
+ *
+ * This file is part of SIP.
+ *
+ * This copy of SIP is licensed for use under the terms of the SIP License
+ * Agreement. See the file LICENSE for more details.
+ *
+ * This copy of SIP may also used under the terms of the GNU General Public
+ * License v2 or v3 as published by the Free Software Foundation which can be
+ * found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package.
+ *
+ * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+#include <string.h>
+
+#include "sip.h"
+#include "sipint.h"
+
+
+#define hash_1(k,s) (((unsigned long)(k)) % (s))
+#define hash_2(k,s) ((s) - 2 - (hash_1((k),(s)) % ((s) - 2)))
+
+
+/* Prime numbers to use as hash table sizes. */
+static unsigned long hash_primes[] = {
+ 521, 1031, 2053, 4099,
+ 8209, 16411, 32771, 65537, 131101, 262147,
+ 524309, 1048583, 2097169, 4194319, 8388617, 16777259,
+ 33554467, 67108879, 134217757, 268435459, 536870923, 1073741827,
+ 2147483659U,0
+};
+
+
+static sipHashEntry *newHashTable(unsigned long);
+static sipHashEntry *findHashEntry(sipObjectMap *,void *);
+static void reorganiseMap(sipObjectMap *om);
+
+
+/*
+ * Initialise an object map.
+ */
+void sipOMInit(sipObjectMap *om)
+{
+ om -> primeIdx = 0;
+ om -> unused = om -> size = hash_primes[om -> primeIdx];
+ om -> stale = 0;
+ om -> hash_array = newHashTable(om -> size);
+}
+
+
+/*
+ * Finalise an object map.
+ */
+void sipOMFinalise(sipObjectMap *om)
+{
+ sip_api_free(om -> hash_array);
+}
+
+
+/*
+ * Allocate and initialise a new hash table.
+ */
+static sipHashEntry *newHashTable(unsigned long size)
+{
+ size_t nbytes;
+ sipHashEntry *hashtab;
+
+ nbytes = sizeof (sipHashEntry) * size;
+
+ if ((hashtab = (sipHashEntry *)sip_api_malloc(nbytes)) != NULL)
+ memset(hashtab,0,nbytes);
+
+ return hashtab;
+}
+
+
+/*
+ * Return a pointer to the hash entry that is used, or should be used, for the
+ * given C/C++ address.
+ */
+static sipHashEntry *findHashEntry(sipObjectMap *om,void *key)
+{
+ unsigned long hash, inc;
+ void *hek;
+
+ hash = hash_1(key,om -> size);
+ inc = hash_2(key,om -> size);
+
+ while ((hek = om -> hash_array[hash].key) != NULL && hek != key)
+ hash = (hash + inc) % om -> size;
+
+ return &om -> hash_array[hash];
+}
+
+
+/*
+ * Return the wrapped Python object of a specific type for a C/C++ address or
+ * NULL if it wasn't found.
+ */
+sipSimpleWrapper *sipOMFindObject(sipObjectMap *om, void *key,
+ const sipTypeDef *td)
+{
+ sipHashEntry *he = findHashEntry(om, key);
+ sipSimpleWrapper *sw;
+ PyTypeObject *py_type = sipTypeAsPyTypeObject(td);
+
+ /* Go through each wrapped object at this address. */
+ for (sw = he->first; sw != NULL; sw = sw->next)
+ {
+ /*
+ * If the reference count is 0 then it is in the process of being
+ * deleted, so ignore it. It's not completely clear how this can
+ * happen (but it can) because it implies that the garbage collection
+ * code is being re-entered (and there are guards in place to prevent
+ * this).
+ */
+ if (Py_REFCNT(sw) == 0)
+ continue;
+
+ /*
+ * If this wrapped object is of the given type, or a sub-type of it,
+ * then we assume it is the same C++ object.
+ */
+ if (PyObject_TypeCheck(sw, py_type))
+ return sw;
+ }
+
+ return NULL;
+}
+
+
+/*
+ * Add a C/C++ address and the corresponding wrapped Python object to the map.
+ */
+void sipOMAddObject(sipObjectMap *om, sipSimpleWrapper *val)
+{
+ sipHashEntry *he = findHashEntry(om, val->u.cppPtr);
+
+ /*
+ * If the bucket is in use then we appear to have several objects at the
+ * same address.
+ */
+ if (he -> first != NULL)
+ {
+ /*
+ * This can happen for three reasons. A variable of one class can be
+ * declared at the start of another class. Therefore there are two
+ * objects, of different classes, with the same address. The second
+ * reason is that the old C/C++ object has been deleted by C/C++ but we
+ * didn't get to find out for some reason, and a new C/C++ instance has
+ * been created at the same address. The third reason is if we are in
+ * the process of deleting a Python object but the C++ object gets
+ * wrapped again because the C++ dtor called a method that has been
+ * re-implemented in Python. The absence of the SIP_SHARE_MAP flag
+ * tells us that a new C++ instance has just been created and so we
+ * know the second reason is the correct one so we mark the old
+ * pointers as invalid and reuse the entry. Otherwise we just add this
+ * one to the existing list of objects at this address.
+ */
+ if (!(val->flags & SIP_SHARE_MAP))
+ {
+ sipSimpleWrapper *sw = he->first;
+
+ he->first = NULL;
+
+ while (sw != NULL)
+ {
+ sipSimpleWrapper *next = sw->next;
+
+ /* We are removing it from the map here. */
+ sipSetNotInMap(sw);
+ sip_api_common_dtor(sw);
+
+ sw = next;
+ }
+ }
+
+ val->next = he->first;
+ he->first = val;
+
+ return;
+ }
+
+ /* See if the bucket was unused or stale. */
+ if (he->key == NULL)
+ {
+ he->key = val -> u.cppPtr;
+ om->unused--;
+ }
+ else
+ om->stale--;
+
+ /* Add the rest of the new value. */
+ he->first = val;
+ val->next = NULL;
+
+ reorganiseMap(om);
+}
+
+
+/*
+ * Reorganise a map if it is running short of space.
+ */
+static void reorganiseMap(sipObjectMap *om)
+{
+ unsigned long old_size, i;
+ sipHashEntry *ohe, *old_tab;
+
+ /* Don't bother if it still has more than 12% available. */
+ if (om -> unused > om -> size >> 3)
+ return;
+
+ /*
+ * If reorganising (ie. making the stale buckets unused) using the same
+ * sized table would make 25% available then do that. Otherwise use a
+ * bigger table (if possible).
+ */
+ if (om -> unused + om -> stale < om -> size >> 2 && hash_primes[om -> primeIdx + 1] != 0)
+ om -> primeIdx++;
+
+ old_size = om -> size;
+ old_tab = om -> hash_array;
+
+ om -> unused = om -> size = hash_primes[om -> primeIdx];
+ om -> stale = 0;
+ om -> hash_array = newHashTable(om -> size);
+
+ /* Transfer the entries from the old table to the new one. */
+ ohe = old_tab;
+
+ for (i = 0; i < old_size; ++i)
+ {
+ if (ohe -> key != NULL && ohe -> first != NULL)
+ {
+ *findHashEntry(om,ohe -> key) = *ohe;
+ om -> unused--;
+ }
+
+ ++ohe;
+ }
+
+ sip_api_free(old_tab);
+}
+
+
+/*
+ * Remove a C/C++ object from the table. Return 0 if it was removed
+ * successfully.
+ */
+int sipOMRemoveObject(sipObjectMap *om, sipSimpleWrapper *val)
+{
+ sipHashEntry *he = findHashEntry(om, val->u.cppPtr);
+ sipSimpleWrapper **swp;
+
+ for (swp = &he->first; *swp != NULL; swp = &(*swp)->next)
+ if (*swp == val)
+ {
+ *swp = val->next;
+
+ /*
+ * If the bucket is now empty then count it as stale. Note that we
+ * do not NULL the key and count it as unused because that might
+ * throw out the search for another entry that wanted to go here,
+ * found it already occupied, and was put somewhere else. In other
+ * words, searches must be repeatable until we reorganise the
+ * table.
+ */
+ if (he->first == NULL)
+ om->stale++;
+
+ return 0;
+ }
+
+ return -1;
+}
diff --git a/siplib/qtlib.c b/siplib/qtlib.c
new file mode 100644
index 0000000..ca0817a
--- /dev/null
+++ b/siplib/qtlib.c
@@ -0,0 +1,659 @@
+/*
+ * The SIP library code that implements the interface to the optional module
+ * supplied Qt support.
+ *
+ * Copyright (c) 2010 Riverbank Computing Limited <info@riverbankcomputing.com>
+ *
+ * This file is part of SIP.
+ *
+ * This copy of SIP is licensed for use under the terms of the SIP License
+ * Agreement. See the file LICENSE for more details.
+ *
+ * This copy of SIP may also used under the terms of the GNU General Public
+ * License v2 or v3 as published by the Free Software Foundation which can be
+ * found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package.
+ *
+ * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+#include <Python.h>
+#include <assert.h>
+#include <string.h>
+
+#include "sip.h"
+#include "sipint.h"
+
+
+/* This is how Qt "types" signals and slots. */
+#define isQtSlot(s) (*(s) == '1')
+#define isQtSignal(s) (*(s) == '2')
+
+
+static PyObject *getWeakRef(PyObject *obj);
+static char *sipStrdup(const char *);
+static void *createUniversalSlot(sipWrapper *txSelf, const char *sig,
+ PyObject *rxObj, const char *slot, const char **member, int flags);
+static void *findSignal(void *txrx, const char **sig);
+static void *newSignal(void *txrx, const char **sig);
+
+
+/*
+ * Find an existing signal.
+ */
+static void *findSignal(void *txrx, const char **sig)
+{
+ if (sipQtSupport->qt_find_universal_signal != NULL)
+ txrx = sipQtSupport->qt_find_universal_signal(txrx, sig);
+
+ return txrx;
+}
+
+
+/*
+ * Return a usable signal, creating a new universal signal if needed.
+ */
+static void *newSignal(void *txrx, const char **sig)
+{
+ void *new_txrx = findSignal(txrx, sig);
+
+ if (new_txrx == NULL && sipQtSupport->qt_create_universal_signal != NULL)
+ new_txrx = sipQtSupport->qt_create_universal_signal(txrx, sig);
+
+ return new_txrx;
+}
+
+
+/*
+ * Create a universal slot. Returns a pointer to it or 0 if there was an
+ * error.
+ */
+static void *createUniversalSlot(sipWrapper *txSelf, const char *sig,
+ PyObject *rxObj, const char *slot, const char **member, int flags)
+{
+ void *us = sipQtSupport->qt_create_universal_slot(txSelf, sig, rxObj, slot,
+ member, flags);
+
+ if (us && txSelf)
+ sipSetPossibleProxy((sipSimpleWrapper *)txSelf);
+
+ return us;
+}
+
+
+/*
+ * Invoke a single slot (Qt or Python) and return the result.
+ */
+PyObject *sip_api_invoke_slot(const sipSlot *slot, PyObject *sigargs)
+{
+ PyObject *sa, *oxtype, *oxvalue, *oxtb, *sfunc, *sref;
+
+ /* Keep some compilers quiet. */
+ oxtype = oxvalue = oxtb = NULL;
+
+ /* Fan out Qt signals. (Only PyQt3 will do this.) */
+ if (slot->name != NULL && slot->name[0] != '\0')
+ {
+ assert(sipQtSupport->qt_emit_signal);
+
+ if (sipQtSupport->qt_emit_signal(slot->pyobj, slot->name, sigargs) < 0)
+ return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ /* Get the object to call, resolving any weak references. */
+ if (slot->weakSlot == Py_True)
+ {
+ /*
+ * The slot is guaranteed to be Ok because it has an extra reference or
+ * is None.
+ */
+ sref = slot->pyobj;
+ Py_INCREF(sref);
+ }
+ else if (slot -> weakSlot == NULL)
+ sref = NULL;
+ else if ((sref = PyWeakref_GetObject(slot -> weakSlot)) == NULL)
+ return NULL;
+ else
+ Py_INCREF(sref);
+
+ if (sref == Py_None)
+ {
+ /*
+ * If the real object has gone then we pretend everything is Ok. This
+ * mimics the Qt behaviour of not caring if a receiving object has been
+ * deleted.
+ */
+ Py_DECREF(sref);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ if (slot -> pyobj == NULL)
+ {
+ PyObject *self = (sref != NULL ? sref : slot->meth.mself);
+
+ /*
+ * If the receiver wraps a C++ object then ignore the call if it no
+ * longer exists.
+ */
+ if (PyObject_TypeCheck(self, (PyTypeObject *)&sipSimpleWrapper_Type) &&
+ sipGetAddress(self) == NULL)
+ {
+ Py_XDECREF(sref);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+#if PY_MAJOR_VERSION >= 3
+ sfunc = PyMethod_New(slot->meth.mfunc, self);
+#else
+ sfunc = PyMethod_New(slot->meth.mfunc, self, slot->meth.mclass);
+#endif
+
+ if (sfunc == NULL)
+ {
+ Py_XDECREF(sref);
+ return NULL;
+ }
+ }
+ else if (slot -> name != NULL)
+ {
+ char *mname = slot -> name + 1;
+ PyObject *self = (sref != NULL ? sref : slot->pyobj);
+
+ if ((sfunc = PyObject_GetAttrString(self, mname)) == NULL || !PyCFunction_Check(sfunc))
+ {
+ /*
+ * Note that in earlier versions of SIP this error would be
+ * detected when the slot was connected.
+ */
+ PyErr_Format(PyExc_NameError,"Invalid slot %s",mname);
+
+ Py_XDECREF(sfunc);
+ Py_XDECREF(sref);
+ return NULL;
+ }
+ }
+ else
+ {
+ sfunc = slot->pyobj;
+ Py_INCREF(sfunc);
+ }
+
+ /*
+ * We make repeated attempts to call a slot. If we work out that it failed
+ * because of an immediate type error we try again with one less argument.
+ * We keep going until we run out of arguments to drop. This emulates the
+ * Qt ability of the slot to accept fewer arguments than a signal provides.
+ */
+ sa = sigargs;
+ Py_INCREF(sa);
+
+ for (;;)
+ {
+ PyObject *nsa, *xtype, *xvalue, *xtb, *resobj;
+
+ if ((resobj = PyEval_CallObject(sfunc, sa)) != NULL)
+ {
+ Py_DECREF(sfunc);
+ Py_XDECREF(sref);
+
+ /* Remove any previous exception. */
+
+ if (sa != sigargs)
+ {
+ Py_XDECREF(oxtype);
+ Py_XDECREF(oxvalue);
+ Py_XDECREF(oxtb);
+ PyErr_Clear();
+ }
+
+ Py_DECREF(sa);
+
+ return resobj;
+ }
+
+ /* Get the exception. */
+ PyErr_Fetch(&xtype,&xvalue,&xtb);
+
+ /*
+ * See if it is unacceptable. An acceptable failure is a type error
+ * with no traceback - so long as we can still reduce the number of
+ * arguments and try again.
+ */
+ if (!PyErr_GivenExceptionMatches(xtype,PyExc_TypeError) ||
+ xtb != NULL ||
+ PyTuple_GET_SIZE(sa) == 0)
+ {
+ /*
+ * If there is a traceback then we must have called the slot and
+ * the exception was later on - so report the exception as is.
+ */
+ if (xtb != NULL)
+ {
+ if (sa != sigargs)
+ {
+ Py_XDECREF(oxtype);
+ Py_XDECREF(oxvalue);
+ Py_XDECREF(oxtb);
+ }
+
+ PyErr_Restore(xtype,xvalue,xtb);
+ }
+ else if (sa == sigargs)
+ PyErr_Restore(xtype,xvalue,xtb);
+ else
+ {
+ /*
+ * Discard the latest exception and restore the original one.
+ */
+ Py_XDECREF(xtype);
+ Py_XDECREF(xvalue);
+ Py_XDECREF(xtb);
+
+ PyErr_Restore(oxtype,oxvalue,oxtb);
+ }
+
+ break;
+ }
+
+ /* If this is the first attempt, save the exception. */
+ if (sa == sigargs)
+ {
+ oxtype = xtype;
+ oxvalue = xvalue;
+ oxtb = xtb;
+ }
+ else
+ {
+ Py_XDECREF(xtype);
+ Py_XDECREF(xvalue);
+ Py_XDECREF(xtb);
+ }
+
+ /* Create the new argument tuple. */
+ if ((nsa = PyTuple_GetSlice(sa,0,PyTuple_GET_SIZE(sa) - 1)) == NULL)
+ {
+ /* Tidy up. */
+ Py_XDECREF(oxtype);
+ Py_XDECREF(oxvalue);
+ Py_XDECREF(oxtb);
+
+ break;
+ }
+
+ Py_DECREF(sa);
+ sa = nsa;
+ }
+
+ Py_DECREF(sfunc);
+ Py_XDECREF(sref);
+
+ Py_DECREF(sa);
+
+ return NULL;
+}
+
+
+/*
+ * Compare two slots to see if they are the same.
+ */
+int sip_api_same_slot(const sipSlot *sp, PyObject *rxObj, const char *slot)
+{
+ /* See if they are signals or Qt slots, ie. they have a name. */
+ if (slot != NULL)
+ {
+ if (sp->name == NULL || sp->name[0] == '\0')
+ return 0;
+
+ return (sipQtSupport->qt_same_name(sp->name, slot) && sp->pyobj == rxObj);
+ }
+
+ /* See if they are pure Python methods. */
+ if (PyMethod_Check(rxObj))
+ {
+ if (sp->pyobj != NULL)
+ return 0;
+
+ return (sp->meth.mfunc == PyMethod_GET_FUNCTION(rxObj)
+ && sp->meth.mself == PyMethod_GET_SELF(rxObj)
+#if PY_MAJOR_VERSION < 3
+ && sp->meth.mclass == PyMethod_GET_CLASS(rxObj)
+#endif
+ );
+ }
+
+ /* See if they are wrapped C++ methods. */
+ if (PyCFunction_Check(rxObj))
+ {
+ if (sp->name == NULL || sp->name[0] != '\0')
+ return 0;
+
+ return (sp->pyobj == PyCFunction_GET_SELF(rxObj) &&
+ strcmp(&sp->name[1], ((PyCFunctionObject *)rxObj)->m_ml->ml_name) == 0);
+ }
+
+ /* The objects must be the same. */
+ return (sp->pyobj == rxObj);
+}
+
+
+/*
+ * Convert a valid Python signal or slot to an existing universal slot.
+ */
+void *sipGetRx(sipSimpleWrapper *txSelf, const char *sigargs, PyObject *rxObj,
+ const char *slot, const char **memberp)
+{
+ if (slot != NULL)
+ if (isQtSlot(slot) || isQtSignal(slot))
+ {
+ void *rx;
+
+ *memberp = slot;
+
+ if ((rx = sip_api_get_cpp_ptr((sipSimpleWrapper *)rxObj, sipQObjectType)) == NULL)
+ return NULL;
+
+ if (isQtSignal(slot))
+ rx = findSignal(rx, memberp);
+
+ return rx;
+ }
+
+ /*
+ * The slot was either a Python callable or PyQt3 Python signal so there
+ * should be a universal slot.
+ */
+ return sipQtSupport->qt_find_slot(sipGetAddress(txSelf), sigargs, rxObj, slot, memberp);
+}
+
+
+/*
+ * Convert a Python receiver (either a Python signal or slot or a Qt signal or
+ * slot) to a Qt receiver. It is only ever called when the signal is a Qt
+ * signal. Return NULL is there was an error.
+ */
+void *sip_api_convert_rx(sipWrapper *txSelf, const char *sigargs,
+ PyObject *rxObj, const char *slot, const char **memberp, int flags)
+{
+ if (slot == NULL)
+ return createUniversalSlot(txSelf, sigargs, rxObj, NULL, memberp, flags);
+
+ if (isQtSlot(slot) || isQtSignal(slot))
+ {
+ void *rx;
+
+ *memberp = slot;
+
+ if ((rx = sip_api_get_cpp_ptr((sipSimpleWrapper *)rxObj, sipQObjectType)) == NULL)
+ return NULL;
+
+ if (isQtSignal(slot))
+ rx = newSignal(rx, memberp);
+
+ return rx;
+ }
+
+ /* The slot is a Python signal so we need a universal slot to catch it. */
+ return createUniversalSlot(txSelf, sigargs, rxObj, slot, memberp, 0);
+}
+
+
+/*
+ * Connect a Qt signal or a Python signal to a Qt slot, a Qt signal, a Python
+ * slot or a Python signal. This is all possible combinations.
+ */
+PyObject *sip_api_connect_rx(PyObject *txObj, const char *sig, PyObject *rxObj,
+ const char *slot, int type)
+{
+ /* Handle Qt signals. */
+ if (isQtSignal(sig))
+ {
+ void *tx, *rx;
+ const char *member, *real_sig;
+ int res;
+
+ if ((tx = sip_api_get_cpp_ptr((sipSimpleWrapper *)txObj, sipQObjectType)) == NULL)
+ return NULL;
+
+ real_sig = sig;
+
+ if ((tx = newSignal(tx, &real_sig)) == NULL)
+ return NULL;
+
+ if ((rx = sip_api_convert_rx((sipWrapper *)txObj, sig, rxObj, slot, &member, 0)) == NULL)
+ return NULL;
+
+ res = sipQtSupport->qt_connect(tx, real_sig, rx, member, type);
+
+ return PyBool_FromLong(res);
+ }
+
+ /* Handle Python signals. Only PyQt3 will get this far. */
+ assert(sipQtSupport->qt_connect_py_signal);
+
+ if (sipQtSupport->qt_connect_py_signal(txObj, sig, rxObj, slot) < 0)
+ return NULL;
+
+ Py_INCREF(Py_True);
+ return Py_True;
+}
+
+
+/*
+ * Disconnect a signal to a signal or a Qt slot.
+ */
+PyObject *sip_api_disconnect_rx(PyObject *txObj,const char *sig,
+ PyObject *rxObj,const char *slot)
+{
+ /* Handle Qt signals. */
+ if (isQtSignal(sig))
+ {
+ sipSimpleWrapper *txSelf = (sipSimpleWrapper *)txObj;
+ void *tx, *rx;
+ const char *member;
+ int res;
+
+ if ((tx = sip_api_get_cpp_ptr(txSelf, sipQObjectType)) == NULL)
+ return NULL;
+
+ if ((rx = sipGetRx(txSelf, sig, rxObj, slot, &member)) == NULL)
+ {
+ Py_INCREF(Py_False);
+ return Py_False;
+ }
+
+ /* Handle Python signals. */
+ tx = findSignal(tx, &sig);
+
+ res = sipQtSupport->qt_disconnect(tx, sig, rx, member);
+
+ /*
+ * Delete it if it is a universal slot as this will be it's only
+ * connection. If the slot is actually a universal signal then it
+ * should leave it in place.
+ */
+ sipQtSupport->qt_destroy_universal_slot(rx);
+
+ return PyBool_FromLong(res);
+ }
+
+ /* Handle Python signals. Only PyQt3 will get this far. */
+ assert(sipQtSupport->qt_disconnect_py_signal);
+
+ sipQtSupport->qt_disconnect_py_signal(txObj, sig, rxObj, slot);
+
+ Py_INCREF(Py_True);
+ return Py_True;
+}
+
+
+/*
+ * Free the resources of a slot.
+ */
+void sip_api_free_sipslot(sipSlot *slot)
+{
+ if (slot->name != NULL)
+ {
+ sip_api_free(slot->name);
+ }
+ else if (slot->weakSlot == Py_True)
+ {
+ Py_DECREF(slot->pyobj);
+ }
+
+ /* Remove any weak reference. */
+ Py_XDECREF(slot->weakSlot);
+}
+
+
+/*
+ * Implement strdup() using sip_api_malloc().
+ */
+static char *sipStrdup(const char *s)
+{
+ char *d;
+
+ if ((d = (char *)sip_api_malloc(strlen(s) + 1)) != NULL)
+ strcpy(d,s);
+
+ return d;
+}
+
+
+/*
+ * Initialise a slot, returning 0 if there was no error. If the signal was a
+ * Qt signal, then the slot may be a Python signal or a Python slot. If the
+ * signal was a Python signal, then the slot may be anything.
+ */
+int sip_api_save_slot(sipSlot *sp, PyObject *rxObj, const char *slot)
+{
+ sp -> weakSlot = NULL;
+
+ if (slot == NULL)
+ {
+ sp -> name = NULL;
+
+ if (PyMethod_Check(rxObj))
+ {
+ /*
+ * Python creates methods on the fly. We could increment the
+ * reference count to keep it alive, but that would keep "self"
+ * alive as well and would probably be a circular reference.
+ * Instead we remember the component parts and hope they are still
+ * valid when we re-create the method when we need it.
+ */
+ sipSaveMethod(&sp -> meth,rxObj);
+
+ /* Notice if the class instance disappears. */
+ sp -> weakSlot = getWeakRef(sp -> meth.mself);
+
+ /* This acts a flag to say that the slot is a method. */
+ sp -> pyobj = NULL;
+ }
+ else
+ {
+ PyObject *self;
+
+ /*
+ * We know that it is another type of callable, ie. a
+ * function/builtin.
+ */
+
+ if (PyCFunction_Check(rxObj) &&
+ (self = PyCFunction_GET_SELF(rxObj)) != NULL &&
+ PyObject_TypeCheck(self, (PyTypeObject *)&sipSimpleWrapper_Type))
+ {
+ /*
+ * It is a wrapped C++ class method. We can't keep a copy
+ * because they are generated on the fly and we can't take a
+ * reference as that may keep the instance (ie. self) alive.
+ * We therefore treat it as if the user had specified the slot
+ * at "obj, SLOT('meth()')" rather than "obj.meth" (see below).
+ */
+
+ const char *meth;
+
+ /* Get the method name. */
+ meth = ((PyCFunctionObject *)rxObj) -> m_ml -> ml_name;
+
+ if ((sp -> name = (char *)sip_api_malloc(strlen(meth) + 2)) == NULL)
+ return -1;
+
+ /*
+ * Copy the name and set the marker that it needs converting to
+ * a built-in method.
+ */
+ sp -> name[0] = '\0';
+ strcpy(&sp -> name[1],meth);
+
+ sp -> pyobj = self;
+ sp -> weakSlot = getWeakRef(self);
+ }
+ else
+ {
+ /*
+ * Give the slot an extra reference to keep it alive and
+ * remember we have done so by treating weakSlot specially.
+ */
+ Py_INCREF(rxObj);
+ sp->pyobj = rxObj;
+
+ Py_INCREF(Py_True);
+ sp->weakSlot = Py_True;
+ }
+ }
+ }
+ else if ((sp -> name = sipStrdup(slot)) == NULL)
+ return -1;
+ else if (isQtSlot(slot))
+ {
+ /*
+ * The user has decided to connect a Python signal to a Qt slot and
+ * specified the slot as "obj, SLOT('meth()')" rather than "obj.meth".
+ */
+
+ char *tail;
+
+ /* Remove any arguments. */
+ if ((tail = strchr(sp -> name,'(')) != NULL)
+ *tail = '\0';
+
+ /*
+ * A bit of a hack to indicate that this needs converting to a built-in
+ * method.
+ */
+ sp -> name[0] = '\0';
+
+ /* Notice if the class instance disappears. */
+ sp -> weakSlot = getWeakRef(rxObj);
+
+ sp -> pyobj = rxObj;
+ }
+ else
+ /* It's a Qt signal. */
+ sp -> pyobj = rxObj;
+
+ return 0;
+}
+
+
+/*
+ * Return a weak reference to the given object.
+ */
+static PyObject *getWeakRef(PyObject *obj)
+{
+ PyObject *wr;
+
+ if ((wr = PyWeakref_NewRef(obj,NULL)) == NULL)
+ PyErr_Clear();
+
+ return wr;
+}
diff --git a/siplib/sip.h b/siplib/sip.h
new file mode 100644
index 0000000..b22b77c
--- /dev/null
+++ b/siplib/sip.h
@@ -0,0 +1,1587 @@
+/*
+ * The SIP module interface.
+ *
+ * Copyright (c) 2010 Riverbank Computing Limited <info@riverbankcomputing.com>
+ *
+ * This file is part of SIP.
+ *
+ * This copy of SIP is licensed for use under the terms of the SIP License
+ * Agreement. See the file LICENSE for more details.
+ *
+ * This copy of SIP may also used under the terms of the GNU General Public
+ * License v2 or v3 as published by the Free Software Foundation which can be
+ * found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package.
+ *
+ * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+#ifndef _SIP_H
+#define _SIP_H
+
+
+/*
+ * This gets round a problem with Qt's moc and Python v2.3. Strictly speaking
+ * it's a Qt problem but later versions of Python include a fix for it so we
+ * might as well too.
+ */
+#undef slots
+
+
+#include <Python.h>
+
+/*
+ * There is a mis-feature somewhere with the Borland compiler. This works
+ * around it.
+ */
+#if defined(__BORLANDC__)
+#include <rpc.h>
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Sanity check on the Python version. */
+#if PY_VERSION_HEX < 0x02030000
+#error "This version of SIP requires Python v2.3 or later"
+#endif
+
+
+/*
+ * Define the SIP version number.
+ */
+#define SIP_VERSION 0x040a05
+#define SIP_VERSION_STR "4.10.5"
+
+
+/*
+ * Define the current API version number. SIP must handle modules with the
+ * same major number and with the same or earlier minor number. Whenever data
+ * structure elements are added they must be appended and the minor number
+ * incremented. Whenever data structure elements are removed or the order
+ * changed then the major number must be incremented and the minor number set
+ * to 0.
+ *
+ * History:
+ *
+ * 7.1 Added the 'H' format character to sip_api_parse_result().
+ * Deprecated the 'D' format character of sip_api_parse_result().
+ *
+ * 7.0 Added sip_api_parse_kwd_args().
+ * Added sipErrorState, sip_api_add_exception().
+ * The type initialisation function is now passed a dictionary of keyword
+ * arguments.
+ * All argument parsers now update a set of error messages rather than an
+ * argument count.
+ * The signatures of sip_api_no_function() and sip_api_no_method() have
+ * changed.
+ * Added ctd_docstring to sipClassTypeDef.
+ * Added vf_docstring to sipVersionedFunctionDef.
+ *
+ * 6.0 Added the sipContainerDef structure to define the contents of a class
+ * or mapped type. Restructured sipClassDef and sipMappedTypeDef
+ * accordingly.
+ * Added the 'r' format character to sip_api_parse_args().
+ * Added the 'r' format character to sip_api_call_method() and
+ * sip_api_build_result().
+ * Added the assignment, array and copy allocation helpers.
+ *
+ * 5.0 Added sip_api_is_api_enabled().
+ * Renamed the td_version_nr member of sipTypeDef to be int and where -1
+ * indicates it is not versioned.
+ * Added the em_versions member to sipExportedModuleDef.
+ * Added the em_versioned_functions member to sipExportedModuleDef.
+ *
+ * 4.0 Much refactoring.
+ *
+ * 3.8 Added sip_api_register_qt_metatype() and sip_api_deprecated().
+ * Added qt_register_meta_type() to the Qt support API.
+ * The C/C++ names of enums and types are now always defined in the
+ * relevant structures and don't default to the Python name.
+ * Added the 'XE' format characters to sip_api_parse_args().
+ *
+ * 3.7 Added sip_api_convert_from_const_void_ptr(),
+ * sip_api_convert_from_void_ptr_and_size() and
+ * sip_api_convert_from_const_void_ptr_and_size().
+ * Added the 'g' and 'G' format characters (to replace the now deprecated
+ * 'a' and 'A' format characters) to sip_api_build_result(),
+ * sip_api_call_method() and sip_api_parse_result().
+ * Added the 'k' and 'K' format characters (to replace the now deprecated
+ * 'a' and 'A' format characters) to sip_api_parse_args().
+ * Added sip_api_invoke_slot().
+ * Added sip_api_parse_type().
+ * Added sip_api_is_exact_wrapped_type().
+ * Added sip_api_assign_instance().
+ * Added sip_api_assign_mapped_type().
+ * Added the td_assign and td_qt fields to the sipTypeDef structure.
+ * Added the mt_assign field to the sipMappedType structure.
+ *
+ * 3.6 Added the 'g' format character to sip_api_parse_args().
+ *
+ * 3.5 Added the td_pickle field to the sipTypeDef structure.
+ * Added sip_api_transfer_break().
+ *
+ * 3.4 Added qt_find_connection() to the Qt support API.
+ * Added sip_api_string_as_char(), sip_api_unicode_as_wchar(),
+ * sip_api_unicode_as_wstring(), sip_api_find_class(),
+ * sip_api_find_named_enum() and sip_api_parse_signature().
+ * Added the 'A', 'w' and 'x' format characters to sip_api_parse_args(),
+ * sip_api_parse_result(), sip_api_build_result() and
+ * sip_api_call_method().
+ *
+ * 3.3 Added sip_api_register_int_types().
+ *
+ * 3.2 Added sip_api_export_symbol() and sip_api_import_symbol().
+ *
+ * 3.1 Added sip_api_add_mapped_type_instance().
+ *
+ * 3.0 Moved the Qt support out of the sip module and into PyQt. This is
+ * such a dramatic change that there is no point in attempting to maintain
+ * backwards compatibility.
+ *
+ * 2.0 Added the td_flags field to the sipTypeDef structure.
+ * Added the first_child, sibling_next, sibling_prev and parent fields to
+ * the sipWrapper structure.
+ * Added the td_traverse and td_clear fields to the sipTypeDef structure.
+ * Added the em_api_minor field to the sipExportedModuleDef structure.
+ * Added sip_api_bad_operator_arg().
+ * Added sip_api_wrapper_check().
+ *
+ * 1.1 Added support for __pos__ and __abs__.
+ *
+ * 1.0 Removed all deprecated parts of the API.
+ * Removed the td_proxy field from the sipTypeDef structure.
+ * Removed the create proxy function from the 'q' and 'y' format
+ * characters to sip_api_parse_args().
+ * Removed sip_api_emit_to_slot().
+ * Reworked the enum related structures.
+ *
+ * 0.2 Added the 'H' format character to sip_api_parse_args().
+ *
+ * 0.1 Added sip_api_add_class_instance().
+ * Added the 't' format character to sip_api_parse_args().
+ * Deprecated the 'J' and 'K' format characters to sip_api_parse_result().
+ *
+ * 0.0 Original version.
+ */
+#define SIP_API_MAJOR_NR 7
+#define SIP_API_MINOR_NR 1
+
+
+/* Some compatibility stuff to help with handwritten code for SIP v3. */
+#if !defined(ANY)
+#define ANY void
+#endif
+
+
+/* Some Python compatibility stuff. */
+#if PY_VERSION_HEX >= 0x02050000
+
+#define SIP_SSIZE_T Py_ssize_t
+
+#define SIP_MLNAME_CAST(s) (s)
+#define SIP_MLDOC_CAST(s) (s)
+#define SIP_TPNAME_CAST(s) (s)
+
+#else
+
+#define SIP_SSIZE_T int
+
+#define SIP_MLNAME_CAST(s) ((char *)(s))
+#define SIP_MLDOC_CAST(s) ((char *)(s))
+#define SIP_TPNAME_CAST(s) ((char *)(s))
+
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+
+#define SIPLong_FromLong PyLong_FromLong
+#define SIPLong_AsLong PyLong_AsLong
+
+#define SIPBytes_Check PyBytes_Check
+#define SIPBytes_FromString PyBytes_FromString
+#define SIPBytes_FromStringAndSize PyBytes_FromStringAndSize
+#define SIPBytes_AS_STRING PyBytes_AS_STRING
+#define SIPBytes_GET_SIZE PyBytes_GET_SIZE
+
+#if PY_MINOR_VERSION >= 1
+#define SIP_USE_PYCAPSULE
+#endif
+
+#else
+
+#define SIPLong_FromLong PyInt_FromLong
+#define SIPLong_AsLong PyInt_AsLong
+
+#define SIPBytes_Check PyString_Check
+#define SIPBytes_FromString PyString_FromString
+#define SIPBytes_FromStringAndSize PyString_FromStringAndSize
+#define SIPBytes_AS_STRING PyString_AS_STRING
+#define SIPBytes_GET_SIZE PyString_GET_SIZE
+
+#if PY_MINOR_VERSION >= 7
+#define SIP_USE_PYCAPSULE
+#endif
+
+#endif
+
+#if !defined(Py_REFCNT)
+#define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt)
+#endif
+
+#if !defined(Py_TYPE)
+#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
+#endif
+
+#if !defined(PyVarObject_HEAD_INIT)
+#define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
+#endif
+
+
+/*
+ * The mask that can be passed to sipTrace().
+ */
+#define SIP_TRACE_CATCHERS 0x0001
+#define SIP_TRACE_CTORS 0x0002
+#define SIP_TRACE_DTORS 0x0004
+#define SIP_TRACE_INITS 0x0008
+#define SIP_TRACE_DEALLOCS 0x0010
+#define SIP_TRACE_METHODS 0x0020
+
+
+/*
+ * Hide some thread dependent stuff.
+ */
+#ifdef WITH_THREAD
+typedef PyGILState_STATE sip_gilstate_t;
+#define SIP_RELEASE_GIL(gs) PyGILState_Release(gs);
+#define SIP_BLOCK_THREADS {PyGILState_STATE sipGIL = PyGILState_Ensure();
+#define SIP_UNBLOCK_THREADS PyGILState_Release(sipGIL);}
+#else
+typedef int sip_gilstate_t;
+#define SIP_RELEASE_GIL(gs)
+#define SIP_BLOCK_THREADS
+#define SIP_UNBLOCK_THREADS
+#endif
+
+
+/*
+ * The meta-type of a wrapper type.
+ */
+typedef struct _sipWrapperType {
+ /*
+ * The super-metatype. This must be first in the structure so that it can
+ * be cast to a PyTypeObject *.
+ */
+ PyHeapTypeObject super;
+
+ /* The generated type structure. */
+ struct _sipTypeDef *type;
+
+ /* The list of init extenders. */
+ struct _sipInitExtenderDef *iextend;
+
+ /* Set if the type's dictionary contains all lazy attributes. */
+ int dict_complete;
+} sipWrapperType;
+
+
+/*
+ * The type of a simple C/C++ wrapper object.
+ */
+typedef struct _sipSimpleWrapper {
+ PyObject_HEAD
+
+ union {
+ /* C/C++ object pointer. */
+ void *cppPtr;
+
+ /* Access function. */
+ void *(*afPtr)();
+ } u;
+
+ /* Object flags. */
+ int flags;
+
+ /* The optional dictionary of extra references keyed by argument number. */
+ PyObject *extra_refs;
+
+ /* For the user to use. */
+ PyObject *user;
+
+ /* The instance dictionary. */
+ PyObject *dict;
+
+ /* Next object at this address. */
+ struct _sipSimpleWrapper *next;
+} sipSimpleWrapper;
+
+
+/*
+ * The type of a C/C++ wrapper object that supports parent/child relationships.
+ */
+typedef struct _sipWrapper {
+ /* The super-type. */
+ sipSimpleWrapper super;
+
+ /* First child object. */
+ struct _sipWrapper *first_child;
+
+ /* Next sibling. */
+ struct _sipWrapper *sibling_next;
+
+ /* Previous sibling. */
+ struct _sipWrapper *sibling_prev;
+
+ /* Owning object. */
+ struct _sipWrapper *parent;
+} sipWrapper;
+
+
+/*
+ * The meta-type of an enum type. (This is exposed only to support the
+ * deprecated sipConvertFromNamedEnum() macro.)
+ */
+typedef struct _sipEnumTypeObject {
+ /*
+ * The super-metatype. This must be first in the structure so that it can
+ * be cast to a PyTypeObject *.
+ */
+ PyHeapTypeObject super;
+
+ /* The generated type structure. */
+ struct _sipTypeDef *type;
+} sipEnumTypeObject;
+
+
+/*
+ * Some convenient function pointers.
+ */
+typedef void *(*sipInitFunc)(sipSimpleWrapper *, PyObject *, PyObject *,
+ PyObject **, PyObject **, PyObject **);
+typedef int (*sipTraverseFunc)(void *, visitproc, void *);
+typedef int (*sipClearFunc)(void *);
+#if PY_MAJOR_VERSION >= 3
+typedef int (*sipGetBufferFunc)(PyObject *, void *, Py_buffer *, int);
+typedef void (*sipReleaseBufferFunc)(PyObject *, void *, Py_buffer *);
+#else
+typedef SIP_SSIZE_T (*sipBufferFunc)(PyObject *, void *, SIP_SSIZE_T, void **);
+typedef SIP_SSIZE_T (*sipSegCountFunc)(PyObject *, void *, SIP_SSIZE_T *);
+#endif
+typedef void (*sipDeallocFunc)(sipSimpleWrapper *);
+typedef void *(*sipCastFunc)(void *, const struct _sipTypeDef *);
+typedef const struct _sipTypeDef *(*sipSubClassConvertFunc)(void **);
+typedef int (*sipConvertToFunc)(PyObject *, void **, int *, PyObject *);
+typedef PyObject *(*sipConvertFromFunc)(void *, PyObject *);
+typedef int (*sipVirtHandlerFunc)(void *, PyObject *, ...);
+typedef void (*sipAssignFunc)(void *, SIP_SSIZE_T, const void *);
+typedef void *(*sipArrayFunc)(SIP_SSIZE_T);
+typedef void *(*sipCopyFunc)(const void *, SIP_SSIZE_T);
+typedef void (*sipReleaseFunc)(void *, int);
+typedef PyObject *(*sipPickleFunc)(void *);
+typedef int (*sipAttrGetterFunc)(const struct _sipTypeDef *, PyObject *);
+typedef PyObject *(*sipVariableGetterFunc)(void *, PyObject *);
+typedef int (*sipVariableSetterFunc)(void *, PyObject *, PyObject *);
+
+
+/*
+ * The information describing an encoded type ID.
+ */
+typedef struct _sipEncodedTypeDef {
+ /* The type number. */
+ unsigned sc_type:16;
+
+ /* The module number (255 for this one). */
+ unsigned sc_module:8;
+
+ /* A context specific flag. */
+ unsigned sc_flag:1;
+} sipEncodedTypeDef;
+
+
+/*
+ * The information describing an enum member.
+ */
+typedef struct _sipEnumMemberDef {
+ /* The member name. */
+ const char *em_name;
+
+ /* The member value. */
+ int em_val;
+
+ /* The member enum, -ve if anonymous. */
+ int em_enum;
+} sipEnumMemberDef;
+
+
+/*
+ * The information describing static instances.
+ */
+typedef struct _sipInstancesDef {
+ /* The types. */
+ struct _sipTypeInstanceDef *id_type;
+
+ /* The void *. */
+ struct _sipVoidPtrInstanceDef *id_voidp;
+
+ /* The chars. */
+ struct _sipCharInstanceDef *id_char;
+
+ /* The strings. */
+ struct _sipStringInstanceDef *id_string;
+
+ /* The ints. */
+ struct _sipIntInstanceDef *id_int;
+
+ /* The longs. */
+ struct _sipLongInstanceDef *id_long;
+
+ /* The unsigned longs. */
+ struct _sipUnsignedLongInstanceDef *id_ulong;
+
+ /* The long longs. */
+ struct _sipLongLongInstanceDef *id_llong;
+
+ /* The unsigned long longs. */
+ struct _sipUnsignedLongLongInstanceDef *id_ullong;
+
+ /* The doubles. */
+ struct _sipDoubleInstanceDef *id_double;
+} sipInstancesDef;
+
+
+/*
+ * The information describing a type initialiser extender.
+ */
+typedef struct _sipInitExtenderDef {
+ /* The API version range index. */
+ int ie_api_range;
+
+ /* The extender function. */
+ sipInitFunc ie_extender;
+
+ /* The class being extended. */
+ sipEncodedTypeDef ie_class;
+
+ /* The next extender for this class. */
+ struct _sipInitExtenderDef *ie_next;
+} sipInitExtenderDef;
+
+
+/*
+ * The information describing a sub-class convertor.
+ */
+typedef struct _sipSubClassConvertorDef {
+ /* The convertor. */
+ sipSubClassConvertFunc scc_convertor;
+
+ /* The encoded base type. */
+ sipEncodedTypeDef scc_base;
+
+ /* The base type. */
+ struct _sipTypeDef *scc_basetype;
+} sipSubClassConvertorDef;
+
+
+/*
+ * The different error states of handwritten code.
+ */
+typedef enum {
+ sipErrorNone, /* There is no error. */
+ sipErrorFail, /* The error is a failure. */
+ sipErrorContinue /* It may not apply if a later operation succeeds. */
+} sipErrorState;
+
+
+/*
+ * The different Python slot types.
+ */
+typedef enum {
+ str_slot, /* __str__ */
+ int_slot, /* __int__ */
+#if PY_MAJOR_VERSION < 3
+ long_slot, /* __long__ */
+#endif
+ float_slot, /* __float__ */
+ len_slot, /* __len__ */
+ contains_slot, /* __contains__ */
+ add_slot, /* __add__ for number */
+ concat_slot, /* __add__ for sequence types */
+ sub_slot, /* __sub__ */
+ mul_slot, /* __mul__ for number types */
+ repeat_slot, /* __mul__ for sequence types */
+ div_slot, /* __div__ */
+ mod_slot, /* __mod__ */
+ floordiv_slot, /* __floordiv__ */
+ truediv_slot, /* __truediv__ */
+ and_slot, /* __and__ */
+ or_slot, /* __or__ */
+ xor_slot, /* __xor__ */
+ lshift_slot, /* __lshift__ */
+ rshift_slot, /* __rshift__ */
+ iadd_slot, /* __iadd__ for number types */
+ iconcat_slot, /* __iadd__ for sequence types */
+ isub_slot, /* __isub__ */
+ imul_slot, /* __imul__ for number types */
+ irepeat_slot, /* __imul__ for sequence types */
+ idiv_slot, /* __idiv__ */
+ imod_slot, /* __imod__ */
+ ifloordiv_slot, /* __ifloordiv__ */
+ itruediv_slot, /* __itruediv__ */
+ iand_slot, /* __iand__ */
+ ior_slot, /* __ior__ */
+ ixor_slot, /* __ixor__ */
+ ilshift_slot, /* __ilshift__ */
+ irshift_slot, /* __irshift__ */
+ invert_slot, /* __invert__ */
+ call_slot, /* __call__ */
+ getitem_slot, /* __getitem__ */
+ setitem_slot, /* __setitem__ */
+ delitem_slot, /* __delitem__ */
+ lt_slot, /* __lt__ */
+ le_slot, /* __le__ */
+ eq_slot, /* __eq__ */
+ ne_slot, /* __ne__ */
+ gt_slot, /* __gt__ */
+ ge_slot, /* __ge__ */
+#if PY_MAJOR_VERSION < 3
+ cmp_slot, /* __cmp__ */
+#endif
+ bool_slot, /* __bool__, __nonzero__ */
+ neg_slot, /* __neg__ */
+ repr_slot, /* __repr__ */
+ hash_slot, /* __hash__ */
+ pos_slot, /* __pos__ */
+ abs_slot, /* __abs__ */
+#if PY_VERSION_HEX >= 0x02050000
+ index_slot, /* __index__ */
+#endif
+ iter_slot, /* __iter__ */
+ next_slot, /* __next__ */
+} sipPySlotType;
+
+
+/*
+ * The information describing a Python slot function.
+ */
+typedef struct _sipPySlotDef {
+ /* The function. */
+ void *psd_func;
+
+ /* The type. */
+ sipPySlotType psd_type;
+} sipPySlotDef;
+
+
+/*
+ * The information describing a Python slot extender.
+ */
+typedef struct _sipPySlotExtenderDef {
+ /* The function. */
+ void *pse_func;
+
+ /* The type. */
+ sipPySlotType pse_type;
+
+ /* The encoded class. */
+ sipEncodedTypeDef pse_class;
+} sipPySlotExtenderDef;
+
+
+/*
+ * The information describing a typedef.
+ */
+typedef struct _sipTypedefDef {
+ /* The typedef name. */
+ const char *tdd_name;
+
+ /* The typedef value. */
+ const char *tdd_type_name;
+} sipTypedefDef;
+
+
+/*
+ * The information describing a variable.
+ */
+typedef struct _sipVariableDef {
+ /* The variable name. */
+ const char *vd_name;
+
+ /* The variable getter. */
+ sipVariableGetterFunc vd_getter;
+
+ /* The variable setter. It is NULL if the variable is const. */
+ sipVariableSetterFunc vd_setter;
+
+ /* This is set if the variable is static. */
+ int vd_is_static;
+} sipVariableDef;
+
+
+/*
+ * The information describing a type, either a C++ class (or C struct), a C++
+ * namespace, a mapped type or a named enum.
+ */
+typedef struct _sipTypeDef {
+ /* The version range index, -1 if the type isn't versioned. */
+ int td_version;
+
+ /* The next version of this type. */
+ struct _sipTypeDef *td_next_version;
+
+ /* The module, 0 if the type hasn't been initialised. */
+ struct _sipExportedModuleDef *td_module;
+
+ /* Type flags, see the sipType*() macros. */
+ int td_flags;
+
+ /* The C/C++ name of the type. */
+ int td_cname;
+
+ /*
+ * The Python type object. This needs to be a union until we remove the
+ * deprecated sipClass_* macros.
+ */
+ union {
+ PyTypeObject *td_py_type;
+ sipWrapperType *td_wrapper_type;
+ } u;
+} sipTypeDef;
+
+
+/*
+ * The information describing a container (ie. a class, namespace or a mapped
+ * type).
+ */
+typedef struct _sipContainerDef {
+ /*
+ * The Python name of the type, -1 if this is a namespace extender (in the
+ * context of a class) or doesn't require a namespace (in the context of a
+ * mapped type). */
+ int cod_name;
+
+ /*
+ * The scoping type or the namespace this is extending if it is a namespace
+ * extender.
+ */
+ sipEncodedTypeDef cod_scope;
+
+ /* The number of lazy methods. */
+ int cod_nrmethods;
+
+ /* The table of lazy methods. */
+ PyMethodDef *cod_methods;
+
+ /* The number of lazy enum members. */
+ int cod_nrenummembers;
+
+ /* The table of lazy enum members. */
+ sipEnumMemberDef *cod_enummembers;
+
+ /* The number of variables. */
+ int cod_nrvariables;
+
+ /* The table of variables. */
+ sipVariableDef *cod_variables;
+
+ /* The static instances. */
+ sipInstancesDef cod_instances;
+} sipContainerDef;
+
+
+/*
+ * The information describing a C++ class (or C struct) or a C++ namespace.
+ */
+typedef struct _sipClassTypeDef {
+ /* The base type information. */
+ sipTypeDef ctd_base;
+
+ /* The container information. */
+ sipContainerDef ctd_container;
+
+ /* The docstring. */
+ const char *ctd_docstring;
+
+ /*
+ * The meta-type name, -1 to use the meta-type of the first super-type
+ * (normally sipWrapperType).
+ */
+ int ctd_metatype;
+
+ /* The super-type name, -1 to use sipWrapper. */
+ int ctd_supertype;
+
+ /* The super-types. */
+ sipEncodedTypeDef *ctd_supers;
+
+ /* The table of Python slots. */
+ sipPySlotDef *ctd_pyslots;
+
+ /* The initialisation function. */
+ sipInitFunc ctd_init;
+
+ /* The traverse function. */
+ sipTraverseFunc ctd_traverse;
+
+ /* The clear function. */
+ sipClearFunc ctd_clear;
+
+#if PY_MAJOR_VERSION >= 3
+ /* The get buffer function. */
+ sipGetBufferFunc ctd_getbuffer;
+
+ /* The release buffer function. */
+ sipReleaseBufferFunc ctd_releasebuffer;
+#else
+ /* The read buffer function. */
+ sipBufferFunc ctd_readbuffer;
+
+ /* The write buffer function. */
+ sipBufferFunc ctd_writebuffer;
+
+ /* The segment count function. */
+ sipSegCountFunc ctd_segcount;
+
+ /* The char buffer function. */
+ sipBufferFunc ctd_charbuffer;
+#endif
+
+ /* The deallocation function. */
+ sipDeallocFunc ctd_dealloc;
+
+ /* The optional assignment function. */
+ sipAssignFunc ctd_assign;
+
+ /* The optional array allocation function. */
+ sipArrayFunc ctd_array;
+
+ /* The optional copy function. */
+ sipCopyFunc ctd_copy;
+
+ /* The release function, 0 if a C strict. */
+ sipReleaseFunc ctd_release;
+
+ /* The cast function, 0 if a C struct. */
+ sipCastFunc ctd_cast;
+
+ /* The optional convert to function. */
+ sipConvertToFunc ctd_cto;
+
+ /* The next namespace extender. */
+ struct _sipClassTypeDef *ctd_nsextender;
+
+ /* The pickle function. */
+ sipPickleFunc ctd_pickle;
+} sipClassTypeDef;
+
+
+/*
+ * The information describing a mapped type.
+ */
+typedef struct _sipMappedTypeDef {
+ /* The base type information. */
+ sipTypeDef mtd_base;
+
+ /* The container information. */
+ sipContainerDef mtd_container;
+
+ /* The optional assignment function. */
+ sipAssignFunc mtd_assign;
+
+ /* The optional array allocation function. */
+ sipArrayFunc mtd_array;
+
+ /* The optional copy function. */
+ sipCopyFunc mtd_copy;
+
+ /* The optional release function. */
+ sipReleaseFunc mtd_release;
+
+ /* The convert to function. */
+ sipConvertToFunc mtd_cto;
+
+ /* The convert from function. */
+ sipConvertFromFunc mtd_cfrom;
+} sipMappedTypeDef;
+
+
+/*
+ * The information describing a named enum.
+ */
+typedef struct _sipEnumTypeDef {
+ /* The base type information. */
+ sipTypeDef etd_base;
+
+ /* The Python name of the enum. */
+ int etd_name;
+
+ /* The scoping type, -1 if it is defined at the module level. */
+ int etd_scope;
+
+ /* The Python slots. */
+ struct _sipPySlotDef *etd_pyslots;
+} sipEnumTypeDef;
+
+
+/*
+ * The information describing an external type.
+ */
+typedef struct _sipExternalTypeDef {
+ /* The index into the type table. */
+ int et_nr;
+
+ /* The name of the type. */
+ const char *et_name;
+} sipExternalTypeDef;
+
+
+/*
+ * The information describing a mapped class. This (and anything that uses it)
+ * is deprecated.
+ */
+typedef sipTypeDef sipMappedType;
+
+
+/*
+ * Defines an entry in the module specific list of delayed dtor calls.
+ */
+typedef struct _sipDelayedDtor {
+ /* The C/C++ instance. */
+ void *dd_ptr;
+
+ /* The class name. */
+ const char *dd_name;
+
+ /* Non-zero if dd_ptr is a derived class instance. */
+ int dd_isderived;
+
+ /* Next in the list. */
+ struct _sipDelayedDtor *dd_next;
+} sipDelayedDtor;
+
+
+/*
+ * Defines an entry in the table of global functions all of whose overloads
+ * are versioned (so their names can't be automatically added to the module
+ * dictionary).
+ */
+typedef struct _sipVersionedFunctionDef {
+ /* The name, -1 marks the end of the table. */
+ int vf_name;
+
+ /* The function itself. */
+ PyCFunction vf_function;
+
+ /* The METH_* flags. */
+ int vf_flags;
+
+ /* The docstring. */
+ const char *vf_docstring;
+
+ /* The API version range index. */
+ int vf_api_range;
+} sipVersionedFunctionDef;
+
+
+/*
+ * The information describing an imported module.
+ */
+typedef struct _sipImportedModuleDef {
+ /* The module name. */
+ const char *im_name;
+
+ /* The required version. */
+ int im_version;
+
+ /* The imported module. */
+ struct _sipExportedModuleDef *im_module;
+} sipImportedModuleDef;
+
+
+/*
+ * The main client module structure.
+ */
+typedef struct _sipExportedModuleDef {
+ /* The next in the list. */
+ struct _sipExportedModuleDef *em_next;
+
+ /* The SIP API minor version number. */
+ unsigned em_api_minor;
+
+ /* The module name. */
+ int em_name;
+
+ /* The module name as an object. */
+ PyObject *em_nameobj;
+
+ /* The module version. */
+ int em_version;
+
+ /* The string pool. */
+ const char *em_strings;
+
+ /* The imported modules. */
+ sipImportedModuleDef *em_imports;
+
+ /* The optional Qt support API. */
+ struct _sipQtAPI *em_qt_api;
+
+ /* The number of types. */
+ int em_nrtypes;
+
+ /* The table of types. */
+ sipTypeDef **em_types;
+
+ /* The table of external types. */
+ sipExternalTypeDef *em_external;
+
+ /* The number of members in global enums. */
+ int em_nrenummembers;
+
+ /* The table of members in global enums. */
+ sipEnumMemberDef *em_enummembers;
+
+ /* The number of typedefs. */
+ int em_nrtypedefs;
+
+ /* The table of typedefs. */
+ sipTypedefDef *em_typedefs;
+
+ /* The table of virtual handlers. */
+ sipVirtHandlerFunc *em_virthandlers;
+
+ /* The sub-class convertors. */
+ sipSubClassConvertorDef *em_convertors;
+
+ /* The static instances. */
+ sipInstancesDef em_instances;
+
+ /* The license. */
+ struct _sipLicenseDef *em_license;
+
+ /* The table of exception types. */
+ PyObject **em_exceptions;
+
+ /* The table of Python slot extenders. */
+ sipPySlotExtenderDef *em_slotextend;
+
+ /* The table of initialiser extenders. */
+ sipInitExtenderDef *em_initextend;
+
+ /* The delayed dtor handler. */
+ void (*em_delayeddtors)(const sipDelayedDtor *);
+
+ /* The list of delayed dtors. */
+ sipDelayedDtor *em_ddlist;
+
+ /*
+ * The array of API version definitions. Each definition takes up 3
+ * elements. If the third element of a 3-tuple is negative then the first
+ * two elements define an API and its default version. All such
+ * definitions will appear at the end of the array. If the first element
+ * of a 3-tuple is negative then that is the last element of the array.
+ */
+ int *em_versions;
+
+ /* The optional table of versioned functions. */
+ sipVersionedFunctionDef *em_versioned_functions;
+} sipExportedModuleDef;
+
+
+/*
+ * The information describing a license to be added to a dictionary.
+ */
+typedef struct _sipLicenseDef {
+ /* The type of license. */
+ const char *lc_type;
+
+ /* The licensee. */
+ const char *lc_licensee;
+
+ /* The timestamp. */
+ const char *lc_timestamp;
+
+ /* The signature. */
+ const char *lc_signature;
+} sipLicenseDef;
+
+
+/*
+ * The information describing a void pointer instance to be added to a
+ * dictionary.
+ */
+typedef struct _sipVoidPtrInstanceDef {
+ /* The void pointer name. */
+ const char *vi_name;
+
+ /* The void pointer value. */
+ void *vi_val;
+} sipVoidPtrInstanceDef;
+
+
+/*
+ * The information describing a char instance to be added to a dictionary.
+ */
+typedef struct _sipCharInstanceDef {
+ /* The char name. */
+ const char *ci_name;
+
+ /* The char value. */
+ char ci_val;
+
+ /* The encoding used, either 'A', 'L', '8' or 'N'. */
+ char ci_encoding;
+} sipCharInstanceDef;
+
+
+/*
+ * The information describing a string instance to be added to a dictionary.
+ */
+typedef struct _sipStringInstanceDef {
+ /* The string name. */
+ const char *si_name;
+
+ /* The string value. */
+ const char *si_val;
+
+ /* The encoding used, either 'A', 'L', '8' or 'N'. */
+ char si_encoding;
+} sipStringInstanceDef;
+
+
+/*
+ * The information describing an int instance to be added to a dictionary.
+ */
+typedef struct _sipIntInstanceDef {
+ /* The int name. */
+ const char *ii_name;
+
+ /* The int value. */
+ int ii_val;
+} sipIntInstanceDef;
+
+
+/*
+ * The information describing a long instance to be added to a dictionary.
+ */
+typedef struct _sipLongInstanceDef {
+ /* The long name. */
+ const char *li_name;
+
+ /* The long value. */
+ long li_val;
+} sipLongInstanceDef;
+
+
+/*
+ * The information describing an unsigned long instance to be added to a
+ * dictionary.
+ */
+typedef struct _sipUnsignedLongInstanceDef {
+ /* The unsigned long name. */
+ const char *uli_name;
+
+ /* The unsigned long value. */
+ unsigned long uli_val;
+} sipUnsignedLongInstanceDef;
+
+
+/*
+ * The information describing a long long instance to be added to a dictionary.
+ */
+typedef struct _sipLongLongInstanceDef {
+ /* The long long name. */
+ const char *lli_name;
+
+ /* The long long value. */
+#if defined(HAVE_LONG_LONG)
+ PY_LONG_LONG lli_val;
+#else
+ long lli_val;
+#endif
+} sipLongLongInstanceDef;
+
+
+/*
+ * The information describing an unsigned long long instance to be added to a
+ * dictionary.
+ */
+typedef struct _sipUnsignedLongLongInstanceDef {
+ /* The unsigned long long name. */
+ const char *ulli_name;
+
+ /* The unsigned long long value. */
+#if defined(HAVE_LONG_LONG)
+ unsigned PY_LONG_LONG ulli_val;
+#else
+ unsigned long ulli_val;
+#endif
+} sipUnsignedLongLongInstanceDef;
+
+
+/*
+ * The information describing a double instance to be added to a dictionary.
+ */
+typedef struct _sipDoubleInstanceDef {
+ /* The double name. */
+ const char *di_name;
+
+ /* The double value. */
+ double di_val;
+} sipDoubleInstanceDef;
+
+
+/*
+ * The information describing a class or enum instance to be added to a
+ * dictionary.
+ */
+typedef struct _sipTypeInstanceDef {
+ /* The type instance name. */
+ const char *ti_name;
+
+ /* The actual instance. */
+ void *ti_ptr;
+
+ /* A pointer to the generated type. */
+ struct _sipTypeDef **ti_type;
+
+ /* The wrapping flags. */
+ int ti_flags;
+} sipTypeInstanceDef;
+
+
+/*
+ * Define a mapping between a wrapped type identified by a string and the
+ * corresponding Python type. This is deprecated.
+ */
+typedef struct _sipStringTypeClassMap {
+ /* The type as a string. */
+ const char *typeString;
+
+ /* A pointer to the Python type. */
+ struct _sipWrapperType **pyType;
+} sipStringTypeClassMap;
+
+
+/*
+ * Define a mapping between a wrapped type identified by an integer and the
+ * corresponding Python type. This is deprecated.
+ */
+typedef struct _sipIntTypeClassMap {
+ /* The type as an integer. */
+ int typeInt;
+
+ /* A pointer to the Python type. */
+ struct _sipWrapperType **pyType;
+} sipIntTypeClassMap;
+
+
+/*
+ * A Python method's component parts. This allows us to re-create the method
+ * without changing the reference counts of the components.
+ */
+typedef struct _sipPyMethod {
+ /* The function. */
+ PyObject *mfunc;
+
+ /* Self if it is a bound method. */
+ PyObject *mself;
+
+#if PY_MAJOR_VERSION < 3
+ /* The class. */
+ PyObject *mclass;
+#endif
+} sipPyMethod;
+
+
+/*
+ * A slot (in the Qt, rather than Python, sense).
+ */
+typedef struct _sipSlot {
+ /* Name if a Qt or Python signal. */
+ char *name;
+
+ /* Signal or Qt slot object. */
+ PyObject *pyobj;
+
+ /* Python slot method, pyobj is NULL. */
+ sipPyMethod meth;
+
+ /* A weak reference to the slot, Py_True if pyobj has an extra reference. */
+ PyObject *weakSlot;
+} sipSlot;
+
+
+/*
+ * The API exported by the SIP module, ie. pointers to all the data and
+ * functions that can be used by generated code.
+ */
+typedef struct _sipAPIDef {
+ /*
+ * This must be the first entry and it's signature must not change so that
+ * version number mismatches can be detected and reported.
+ */
+ int (*api_export_module)(sipExportedModuleDef *client, unsigned api_major,
+ unsigned api_minor, void *unused);
+
+ /*
+ * The following are part of the public API.
+ */
+ PyTypeObject *api_simplewrapper_type;
+ PyTypeObject *api_wrapper_type;
+ PyTypeObject *api_wrappertype_type;
+ PyTypeObject *api_voidptr_type;
+
+ void (*api_bad_catcher_result)(PyObject *method);
+ void (*api_bad_length_for_slice)(SIP_SSIZE_T seqlen, SIP_SSIZE_T slicelen);
+ PyObject *(*api_build_result)(int *isErr, const char *fmt, ...);
+ PyObject *(*api_call_method)(int *isErr, PyObject *method, const char *fmt,
+ ...);
+ PyObject *(*api_connect_rx)(PyObject *txObj, const char *sig,
+ PyObject *rxObj, const char *slot, int type);
+ SIP_SSIZE_T (*api_convert_from_sequence_index)(SIP_SSIZE_T idx,
+ SIP_SSIZE_T len);
+ int (*api_can_convert_to_type)(PyObject *pyObj, const sipTypeDef *td,
+ int flags);
+ void *(*api_convert_to_type)(PyObject *pyObj, const sipTypeDef *td,
+ PyObject *transferObj, int flags, int *statep, int *iserrp);
+ void *(*api_force_convert_to_type)(PyObject *pyObj, const sipTypeDef *td,
+ PyObject *transferObj, int flags, int *statep, int *iserrp);
+ int (*api_can_convert_to_enum)(PyObject *pyObj, const sipTypeDef *td);
+ void (*api_release_type)(void *cpp, const sipTypeDef *td, int state);
+ PyObject *(*api_convert_from_type)(void *cpp, const sipTypeDef *td,
+ PyObject *transferObj);
+ PyObject *(*api_convert_from_new_type)(void *cpp, const sipTypeDef *td,
+ PyObject *transferObj);
+ PyObject *(*api_convert_from_enum)(int eval, const sipTypeDef *td);
+ int (*api_get_state)(PyObject *transferObj);
+ PyObject *(*api_disconnect_rx)(PyObject *txObj, const char *sig,
+ PyObject *rxObj, const char *slot);
+ void (*api_free)(void *mem);
+ PyObject *(*api_get_pyobject)(void *cppPtr, const sipTypeDef *td);
+ void *(*api_malloc)(size_t nbytes);
+ int (*api_parse_result)(int *isErr, PyObject *method, PyObject *res,
+ const char *fmt, ...);
+ void (*api_trace)(unsigned mask, const char *fmt, ...);
+ void (*api_transfer_back)(PyObject *self);
+ void (*api_transfer_to)(PyObject *self, PyObject *owner);
+ void (*api_transfer_break)(PyObject *self);
+ unsigned long (*api_long_as_unsigned_long)(PyObject *o);
+ PyObject *(*api_convert_from_void_ptr)(void *val);
+ PyObject *(*api_convert_from_const_void_ptr)(const void *val);
+ PyObject *(*api_convert_from_void_ptr_and_size)(void *val,
+ SIP_SSIZE_T size);
+ PyObject *(*api_convert_from_const_void_ptr_and_size)(const void *val,
+ SIP_SSIZE_T size);
+ void *(*api_convert_to_void_ptr)(PyObject *obj);
+ int (*api_export_symbol)(const char *name, void *sym);
+ void *(*api_import_symbol)(const char *name);
+ const sipTypeDef *(*api_find_type)(const char *type);
+ int (*api_register_py_type)(PyTypeObject *type);
+ const sipTypeDef *(*api_type_from_py_type_object)(PyTypeObject *py_type);
+ const sipTypeDef *(*api_type_scope)(const sipTypeDef *td);
+ const char *(*api_resolve_typedef)(const char *name);
+ int (*api_register_attribute_getter)(const sipTypeDef *td,
+ sipAttrGetterFunc getter);
+ int (*api_is_api_enabled)(const char *name, int from, int to);
+ sipErrorState (*api_bad_callable_arg)(int arg_nr, PyObject *arg);
+
+ /*
+ * The following are deprecated parts of the public API.
+ */
+ PyTypeObject *(*api_find_named_enum)(const char *type);
+ const sipMappedType *(*api_find_mapped_type)(const char *type);
+ sipWrapperType *(*api_find_class)(const char *type);
+ sipWrapperType *(*api_map_int_to_class)(int typeInt,
+ const sipIntTypeClassMap *map, int maplen);
+ sipWrapperType *(*api_map_string_to_class)(const char *typeString,
+ const sipStringTypeClassMap *map, int maplen);
+
+ /*
+ * The following may be used by Qt support code but no other handwritten
+ * code.
+ */
+ void (*api_free_sipslot)(sipSlot *slot);
+ int (*api_same_slot)(const sipSlot *sp, PyObject *rxObj, const char *slot);
+ void *(*api_convert_rx)(sipWrapper *txSelf, const char *sigargs,
+ PyObject *rxObj, const char *slot, const char **memberp,
+ int flags);
+ PyObject *(*api_invoke_slot)(const sipSlot *slot, PyObject *sigargs);
+ int (*api_save_slot)(sipSlot *sp, PyObject *rxObj, const char *slot);
+ void (*api_clear_any_slot_reference)(sipSlot *slot);
+ int (*api_visit_slot)(sipSlot *slot, visitproc visit, void *arg);
+
+ /*
+ * The following are not part of the public API.
+ */
+ int (*api_init_module)(sipExportedModuleDef *client, PyObject *mod_dict);
+ int (*api_parse_args)(PyObject **parseErrp, PyObject *sipArgs,
+ const char *fmt, ...);
+ int (*api_parse_pair)(PyObject **parseErrp, PyObject *arg0, PyObject *arg1,
+ const char *fmt, ...);
+ void (*api_common_dtor)(sipSimpleWrapper *sipSelf);
+ void (*api_no_function)(PyObject *parseErr, const char *func,
+ const char *doc);
+ void (*api_no_method)(PyObject *parseErr, const char *scope,
+ const char *method, const char *doc);
+ void (*api_abstract_method)(const char *classname, const char *method);
+ void (*api_bad_class)(const char *classname);
+ void *(*api_get_cpp_ptr)(sipSimpleWrapper *w, const sipTypeDef *td);
+ void *(*api_get_complex_cpp_ptr)(sipSimpleWrapper *w);
+ PyObject *(*api_is_py_method)(sip_gilstate_t *gil, char *pymc,
+ sipSimpleWrapper *sipSelf, const char *cname, const char *mname);
+ void (*api_call_hook)(const char *hookname);
+ void (*api_start_thread)(void);
+ void (*api_end_thread)(void);
+ void (*api_raise_unknown_exception)(void);
+ void (*api_raise_type_exception)(const sipTypeDef *td, void *ptr);
+ int (*api_add_type_instance)(PyObject *dict, const char *name,
+ void *cppPtr, const sipTypeDef *td);
+ void (*api_bad_operator_arg)(PyObject *self, PyObject *arg,
+ sipPySlotType st);
+ PyObject *(*api_pyslot_extend)(sipExportedModuleDef *mod, sipPySlotType st,
+ const sipTypeDef *type, PyObject *arg0, PyObject *arg1);
+ void (*api_add_delayed_dtor)(sipSimpleWrapper *w);
+ char (*api_bytes_as_char)(PyObject *obj);
+ const char *(*api_bytes_as_string)(PyObject *obj);
+ char (*api_string_as_ascii_char)(PyObject *obj);
+ const char *(*api_string_as_ascii_string)(PyObject **obj);
+ char (*api_string_as_latin1_char)(PyObject *obj);
+ const char *(*api_string_as_latin1_string)(PyObject **obj);
+ char (*api_string_as_utf8_char)(PyObject *obj);
+ const char *(*api_string_as_utf8_string)(PyObject **obj);
+#if defined(HAVE_WCHAR_H)
+ wchar_t (*api_unicode_as_wchar)(PyObject *obj);
+ wchar_t *(*api_unicode_as_wstring)(PyObject *obj);
+#else
+ int (*api_unicode_as_wchar)(PyObject *obj);
+ int *(*api_unicode_as_wstring)(PyObject *obj);
+#endif
+ int (*api_deprecated)(const char *classname, const char *method);
+ void (*api_keep_reference)(PyObject *self, int key, PyObject *obj);
+ int (*api_parse_kwd_args)(PyObject **parseErrp, PyObject *sipArgs,
+ PyObject *sipKwdArgs, const char **kwdlist, PyObject **unused,
+ const char *fmt, ...);
+ void (*api_add_exception)(sipErrorState es, PyObject **parseErrp);
+} sipAPIDef;
+
+
+/*
+ * The API implementing the optional Qt support.
+ */
+typedef struct _sipQtAPI {
+ sipTypeDef **qt_qobject;
+ void *(*qt_create_universal_signal)(void *, const char **);
+ void *(*qt_find_universal_signal)(void *, const char **);
+ void *(*qt_create_universal_slot)(struct _sipWrapper *, const char *,
+ PyObject *, const char *, const char **, int);
+ void (*qt_destroy_universal_slot)(void *);
+ void *(*qt_find_slot)(void *, const char *, PyObject *, const char *,
+ const char **);
+ int (*qt_connect)(void *, const char *, void *, const char *, int);
+ int (*qt_disconnect)(void *, const char *, void *, const char *);
+ int (*qt_same_name)(const char *, const char *);
+ sipSlot *(*qt_find_sipslot)(void *, void **);
+ int (*qt_emit_signal)(PyObject *, const char *, PyObject *);
+ int (*qt_connect_py_signal)(PyObject *, const char *, PyObject *,
+ const char *);
+ void (*qt_disconnect_py_signal)(PyObject *, const char *, PyObject *,
+ const char *);
+} sipQtAPI;
+
+
+/*
+ * These are flags that can be passed to sipCanConvertToType(),
+ * sipConvertToType() and sipForceConvertToType().
+ */
+#define SIP_NOT_NONE 0x01 /* Disallow None. */
+#define SIP_NO_CONVERTORS 0x02 /* Disable any type convertors. */
+
+
+/*
+ * These are the state flags returned by %ConvertToTypeCode. Note that these
+ * share the same "namespace" as the flags below.
+ */
+#define SIP_TEMPORARY 0x0001 /* A temporary instance. */
+#define SIP_DERIVED_CLASS 0x0002 /* The instance is derived. */
+
+
+/*
+ * These flags are specific to the Qt support API.
+ */
+#define SIP_SINGLE_SHOT 0x01 /* The connection is single shot. */
+
+
+/*
+ * Useful macros, not part of the public API.
+ */
+#define SIP_PY_OWNED 0x0004 /* Owned by Python. */
+#define SIP_INDIRECT 0x0008 /* If there is a level of indirection. */
+#define SIP_ACCFUNC 0x0010 /* If there is an access function. */
+#define SIP_NOT_IN_MAP 0x0020 /* If Python object not in the map. */
+#define SIP_SHARE_MAP 0x0040 /* If the map slot might be occupied. */
+#define SIP_CPP_HAS_REF 0x0080 /* If C/C++ has a reference. */
+#define SIP_POSSIBLE_PROXY 0x0100 /* If there might be a proxy slot. */
+
+#define sipIsPyOwned(w) ((w)->flags & SIP_PY_OWNED)
+#define sipSetPyOwned(w) ((w)->flags |= SIP_PY_OWNED)
+#define sipResetPyOwned(w) ((w)->flags &= ~SIP_PY_OWNED)
+#define sipIsDerived(w) ((w)->flags & SIP_DERIVED_CLASS)
+#define sipIsIndirect(w) ((w)->flags & SIP_INDIRECT)
+#define sipIsAccessFunc(w) ((w)->flags & SIP_ACCFUNC)
+#define sipNotInMap(w) ((w)->flags & SIP_NOT_IN_MAP)
+#define sipSetNotInMap(w) ((w)->flags |= SIP_NOT_IN_MAP)
+#define sipCppHasRef(w) ((w)->flags & SIP_CPP_HAS_REF)
+#define sipSetCppHasRef(w) ((w)->flags |= SIP_CPP_HAS_REF)
+#define sipResetCppHasRef(w) ((w)->flags &= ~SIP_CPP_HAS_REF)
+#define sipPossibleProxy(w) ((w)->flags & SIP_POSSIBLE_PROXY)
+#define sipSetPossibleProxy(w) ((w)->flags |= SIP_POSSIBLE_PROXY)
+
+
+#define SIP_TYPE_TYPE_MASK 0x0007 /* The type type mask. */
+#define SIP_TYPE_CLASS 0x0000 /* If the type is a C++ class. */
+#define SIP_TYPE_NAMESPACE 0x0001 /* If the type is a C++ namespace. */
+#define SIP_TYPE_MAPPED 0x0002 /* If the type is a mapped type. */
+#define SIP_TYPE_ENUM 0x0003 /* If the type is a named enum. */
+#define SIP_TYPE_ABSTRACT 0x0008 /* If the type is abstract. */
+#define SIP_TYPE_SCC 0x0010 /* If the type is subject to sub-class convertors. */
+#define SIP_TYPE_ALLOW_NONE 0x0020 /* If the type can handle None. */
+#define SIP_TYPE_STUB 0x0040 /* If the type is a stub. */
+
+
+/*
+ * The following are part of the public API.
+ */
+#define sipTypeIsClass(td) (((td)->td_flags & SIP_TYPE_TYPE_MASK) == SIP_TYPE_CLASS)
+#define sipTypeIsNamespace(td) (((td)->td_flags & SIP_TYPE_TYPE_MASK) == SIP_TYPE_NAMESPACE)
+#define sipTypeIsMapped(td) (((td)->td_flags & SIP_TYPE_TYPE_MASK) == SIP_TYPE_MAPPED)
+#define sipTypeIsEnum(td) (((td)->td_flags & SIP_TYPE_TYPE_MASK) == SIP_TYPE_ENUM)
+#define sipTypeAsPyTypeObject(td) ((td)->u.td_py_type)
+#define sipTypeName(td) sipNameFromPool((td)->td_module, (td)->td_cname)
+
+#define sipIsExactWrappedType(wt) (sipTypeAsPyTypeObject((wt)->type) == (PyTypeObject *)(wt))
+
+#define sipConvertFromSliceObject(o,len,start,stop,step,slen) \
+ PySlice_GetIndicesEx((PySliceObject *)(o), (len), (start), (stop), \
+ (step), (slen))
+
+
+/*
+ * The following are deprecated parts of the public API.
+ */
+#define sipClassName(w) PyString_FromString(Py_TYPE(w)->tp_name)
+
+
+/*
+ * The following are not part of the public API.
+ */
+#define sipTypeIsAbstract(td) ((td)->td_flags & SIP_TYPE_ABSTRACT)
+#define sipTypeHasSCC(td) ((td)->td_flags & SIP_TYPE_SCC)
+#define sipTypeAllowNone(td) ((td)->td_flags & SIP_TYPE_ALLOW_NONE)
+#define sipTypeIsStub(td) ((td)->td_flags & SIP_TYPE_STUB)
+#define sipTypeSetStub(td) ((td)->td_flags |= SIP_TYPE_STUB)
+
+/*
+ * Get various names from the string pool for various data types.
+ */
+#define sipNameFromPool(em, mr) (&((em)->em_strings)[(mr)])
+#define sipNameOfModule(em) sipNameFromPool((em), (em)->em_name)
+#define sipPyNameOfContainer(cod, td) sipNameFromPool((td)->td_module, (cod)->cod_name)
+#define sipPyNameOfEnum(etd) sipNameFromPool((etd)->etd_base.td_module, (etd)->etd_name)
+
+
+/*
+ * The following are PyQt3-specific extensions. In SIP v5 they will be pushed
+ * out to a plugin supplied by PyQt3.
+ */
+
+typedef int (*pyqt3EmitFunc)(sipSimpleWrapper *, PyObject *);
+
+
+/*
+ * Maps the name of a Qt signal to a wrapper function to emit it.
+ */
+typedef struct _pyqt3QtSignal {
+ /* The signal name. */
+ const char *st_name;
+
+ /* The emitter function. */
+ pyqt3EmitFunc st_emitfunc;
+} pyqt3QtSignal;
+
+
+/*
+ * This is the PyQt3-specific extension to the generated class type structure.
+ */
+typedef struct _pyqt3ClassTypeDef {
+ /*
+ * The super-type structure. This must be first in the structure so that
+ * it can be cast to sipClassTypeDef *.
+ */
+ sipClassTypeDef super;
+
+ /* The emit table for Qt signals. */
+ pyqt3QtSignal *qt3_emit;
+} pyqt3ClassTypeDef;
+
+
+/*
+ * The following are PyQt4-specific extensions. In SIP v5 they will be pushed
+ * out to a plugin supplied by PyQt4.
+ */
+
+/*
+ * The description of a Qt signal for PyQt4.
+ */
+typedef struct _pyqt4QtSignal {
+ /* The C++ name and signature of the signal. */
+ const char *signature;
+
+ /* The optional docstring. */
+ const char *docstring;
+
+ /*
+ * If the signal is an overload of regular methods then this points to the
+ * code that implements those methods.
+ */
+ PyMethodDef *non_signals;
+} pyqt4QtSignal;
+
+
+/*
+ * This is the PyQt4-specific extension to the generated class type structure.
+ */
+typedef struct _pyqt4ClassTypeDef {
+ /*
+ * The super-type structure. This must be first in the structure so that
+ * it can be cast to sipClassTypeDef *.
+ */
+ sipClassTypeDef super;
+
+ /* A pointer to the QObject sub-class's staticMetaObject class variable. */
+ const void *qt4_static_metaobject;
+
+ /*
+ * A set of flags. At the moment only bit 0 is used to say if the type is
+ * derived from QFlags.
+ */
+ unsigned qt4_flags;
+
+ /*
+ * The table of signals emitted by the type. These are grouped by signal
+ * name.
+ */
+ const pyqt4QtSignal *qt4_signals;
+} pyqt4ClassTypeDef;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/siplib/sipint.h b/siplib/sipint.h
new file mode 100644
index 0000000..19a8b1b
--- /dev/null
+++ b/siplib/sipint.h
@@ -0,0 +1,149 @@
+/*
+ * This file defines the SIP library internal interfaces.
+ *
+ * Copyright (c) 2010 Riverbank Computing Limited <info@riverbankcomputing.com>
+ *
+ * This file is part of SIP.
+ *
+ * This copy of SIP is licensed for use under the terms of the SIP License
+ * Agreement. See the file LICENSE for more details.
+ *
+ * This copy of SIP may also used under the terms of the GNU General Public
+ * License v2 or v3 as published by the Free Software Foundation which can be
+ * found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package.
+ *
+ * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+#ifndef _SIPINT_H
+#define _SIPINT_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#undef TRUE
+#define TRUE 1
+
+#undef FALSE
+#define FALSE 0
+
+
+/*
+ * This defines a single entry in an object map's hash table.
+ */
+typedef struct
+{
+ void *key; /* The C/C++ address. */
+ sipSimpleWrapper *first; /* The first object at this address. */
+} sipHashEntry;
+
+
+/*
+ * This defines the interface to a hash table class for mapping C/C++ addresses
+ * to the corresponding wrapped Python object.
+ */
+typedef struct
+{
+ int primeIdx; /* Index into table sizes. */
+ unsigned long size; /* Size of hash table. */
+ unsigned long unused; /* Nr. unused in hash table. */
+ unsigned long stale; /* Nr. stale in hash table. */
+ sipHashEntry *hash_array; /* Current hash table. */
+} sipObjectMap;
+
+
+/*
+ * Support for the descriptors.
+ */
+extern PyTypeObject sipMethodDescr_Type;
+PyObject *sipMethodDescr_New(PyMethodDef *pmd);
+
+extern PyTypeObject sipVariableDescr_Type;
+PyObject *sipVariableDescr_New(sipVariableDef *vd, const sipTypeDef *td,
+ const sipContainerDef *cod);
+
+
+/*
+ * Support for API versions.
+ */
+PyObject *sipGetAPI(PyObject *self, PyObject *args);
+PyObject *sipSetAPI(PyObject *self, PyObject *args);
+int sip_api_is_api_enabled(const char *name, int from, int to);
+int sipIsRangeEnabled(sipExportedModuleDef *em, int range_index);
+int sipInitAPI(sipExportedModuleDef *em, PyObject *mod_dict);
+
+
+/*
+ * Support for void pointers.
+ */
+extern PyTypeObject sipVoidPtr_Type;
+void *sip_api_convert_to_void_ptr(PyObject *obj);
+PyObject *sip_api_convert_from_void_ptr(void *val);
+PyObject *sip_api_convert_from_const_void_ptr(const void *val);
+PyObject *sip_api_convert_from_void_ptr_and_size(void *val, SIP_SSIZE_T size);
+PyObject *sip_api_convert_from_const_void_ptr_and_size(const void *val,
+ SIP_SSIZE_T size);
+
+
+extern sipQtAPI *sipQtSupport; /* The Qt support API. */
+extern sipWrapperType sipSimpleWrapper_Type; /* The simple wrapper type. */
+extern sipTypeDef *sipQObjectType; /* The QObject type. */
+
+void *sipGetRx(sipSimpleWrapper *txSelf, const char *sigargs, PyObject *rxObj,
+ const char *slot, const char **memberp);
+PyObject *sip_api_connect_rx(PyObject *txObj, const char *sig, PyObject *rxObj,
+ const char *slot, int type);
+PyObject *sip_api_disconnect_rx(PyObject *txObj, const char *sig,
+ PyObject *rxObj,const char *slot);
+
+
+/*
+ * These are part of the SIP API but are also used within the SIP module.
+ */
+void *sip_api_malloc(size_t nbytes);
+void sip_api_free(void *mem);
+void *sip_api_get_cpp_ptr(sipSimpleWrapper *w, const sipTypeDef *td);
+PyObject *sip_api_convert_from_type(void *cppPtr, const sipTypeDef *td,
+ PyObject *transferObj);
+void sip_api_common_dtor(sipSimpleWrapper *sipSelf);
+void sip_api_start_thread(void);
+void sip_api_end_thread(void);
+void sip_api_free_sipslot(sipSlot *slot);
+int sip_api_same_slot(const sipSlot *sp, PyObject *rxObj, const char *slot);
+PyObject *sip_api_invoke_slot(const sipSlot *slot, PyObject *sigargs);
+void *sip_api_convert_rx(sipWrapper *txSelf, const char *sigargs,
+ PyObject *rxObj, const char *slot, const char **memberp, int flags);
+int sip_api_save_slot(sipSlot *sp, PyObject *rxObj, const char *slot);
+
+
+/*
+ * These are not part of the SIP API but are used within the SIP module.
+ */
+void sipSaveMethod(sipPyMethod *pm,PyObject *meth);
+void *sipGetPending(sipWrapper **op, int *fp);
+PyObject *sipWrapSimpleInstance(void *cppPtr, const sipTypeDef *td,
+ sipWrapper *owner, int initflags);
+void *sipConvertRxEx(sipWrapper *txSelf, const char *sigargs,
+ PyObject *rxObj, const char *slot, const char **memberp, int flags);
+
+void sipOMInit(sipObjectMap *om);
+void sipOMFinalise(sipObjectMap *om);
+sipSimpleWrapper *sipOMFindObject(sipObjectMap *om, void *key,
+ const sipTypeDef *td);
+void sipOMAddObject(sipObjectMap *om, sipSimpleWrapper *val);
+int sipOMRemoveObject(sipObjectMap *om, sipSimpleWrapper *val);
+
+void sipSetBool(void *ptr,int val);
+
+void *sipGetAddress(sipSimpleWrapper *w);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/siplib/siplib.c b/siplib/siplib.c
new file mode 100644
index 0000000..f419b6b
--- /dev/null
+++ b/siplib/siplib.c
@@ -0,0 +1,10501 @@
+/*
+ * SIP library code.
+ *
+ * Copyright (c) 2010 Riverbank Computing Limited <info@riverbankcomputing.com>
+ *
+ * This file is part of SIP.
+ *
+ * This copy of SIP is licensed for use under the terms of the SIP License
+ * Agreement. See the file LICENSE for more details.
+ *
+ * This copy of SIP may also used under the terms of the GNU General Public
+ * License v2 or v3 as published by the Free Software Foundation which can be
+ * found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package.
+ *
+ * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+#include <Python.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "sip.h"
+#include "sipint.h"
+
+
+/* There doesn't seem to be a standard way of checking for C99 support. */
+#if !defined(va_copy)
+#define va_copy(d, s) ((d) = (s))
+#endif
+
+
+/*
+ * The Python metatype for a C++ wrapper type. We inherit everything from the
+ * standard Python metatype except the init and getattro methods and the size
+ * of the type object created is increased to accomodate the extra information
+ * we associate with a wrapped type.
+ */
+
+static PyObject *sipWrapperType_alloc(PyTypeObject *self, SIP_SSIZE_T nitems);
+static PyObject *sipWrapperType_getattro(PyObject *self, PyObject *name);
+static int sipWrapperType_init(sipWrapperType *self, PyObject *args,
+ PyObject *kwds);
+static int sipWrapperType_setattro(PyObject *self, PyObject *name,
+ PyObject *value);
+
+static PyTypeObject sipWrapperType_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "sip.wrappertype", /* tp_name */
+ sizeof (sipWrapperType), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved (Python v3), tp_compare (Python v2) */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ sipWrapperType_getattro, /* tp_getattro */
+ sipWrapperType_setattro, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)sipWrapperType_init, /* tp_init */
+ sipWrapperType_alloc, /* tp_alloc */
+ 0, /* tp_new */
+ 0, /* tp_free */
+};
+
+
+/*
+ * The Python type that is the super-type for all C++ wrapper types that
+ * support parent/child relationships.
+ */
+
+static int sipWrapper_clear(sipWrapper *self);
+static void sipWrapper_dealloc(sipWrapper *self);
+static int sipWrapper_traverse(sipWrapper *self, visitproc visit, void *arg);
+
+static sipWrapperType sipWrapper_Type = {
+#if !defined(STACKLESS)
+ {
+#endif
+ {
+ PyVarObject_HEAD_INIT(&sipWrapperType_Type, 0)
+ "sip.wrapper", /* tp_name */
+ sizeof (sipWrapper), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)sipWrapper_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved (Python v3), tp_compare (Python v2) */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
+ 0, /* tp_doc */
+ (traverseproc)sipWrapper_traverse, /* tp_traverse */
+ (inquiry)sipWrapper_clear, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+ 0, /* tp_free */
+ },
+#if !defined(STACKLESS)
+ },
+#endif
+ 0,
+ 0
+};
+
+
+static void sip_api_bad_catcher_result(PyObject *method);
+static void sip_api_bad_length_for_slice(SIP_SSIZE_T seqlen,
+ SIP_SSIZE_T slicelen);
+static PyObject *sip_api_build_result(int *isErr, const char *fmt, ...);
+static PyObject *sip_api_call_method(int *isErr, PyObject *method,
+ const char *fmt, ...);
+static SIP_SSIZE_T sip_api_convert_from_sequence_index(SIP_SSIZE_T idx,
+ SIP_SSIZE_T len);
+static int sip_api_can_convert_to_type(PyObject *pyObj, const sipTypeDef *td,
+ int flags);
+static void *sip_api_convert_to_type(PyObject *pyObj, const sipTypeDef *td,
+ PyObject *transferObj, int flags, int *statep, int *iserrp);
+static void *sip_api_force_convert_to_type(PyObject *pyObj,
+ const sipTypeDef *td, PyObject *transferObj, int flags, int *statep,
+ int *iserrp);
+static int sip_api_can_convert_to_enum(PyObject *pyObj, const sipTypeDef *td);
+static void sip_api_release_type(void *cpp, const sipTypeDef *td, int state);
+static PyObject *sip_api_convert_from_new_type(void *cpp, const sipTypeDef *td,
+ PyObject *transferObj);
+static int sip_api_get_state(PyObject *transferObj);
+static PyObject *sip_api_get_pyobject(void *cppPtr, const sipTypeDef *td);
+static sipWrapperType *sip_api_map_int_to_class(int typeInt,
+ const sipIntTypeClassMap *map, int maplen);
+static sipWrapperType *sip_api_map_string_to_class(const char *typeString,
+ const sipStringTypeClassMap *map, int maplen);
+static int sip_api_parse_result(int *isErr, PyObject *method, PyObject *res,
+ const char *fmt, ...);
+static void sip_api_trace(unsigned mask,const char *fmt,...);
+static void sip_api_transfer_back(PyObject *self);
+static void sip_api_transfer_to(PyObject *self, PyObject *owner);
+static int sip_api_export_module(sipExportedModuleDef *client,
+ unsigned api_major, unsigned api_minor, void *unused);
+static int sip_api_init_module(sipExportedModuleDef *client,
+ PyObject *mod_dict);
+static int sip_api_parse_args(PyObject **parseErrp, PyObject *sipArgs,
+ const char *fmt, ...);
+static int sip_api_parse_kwd_args(PyObject **parseErrp, PyObject *sipArgs,
+ PyObject *sipKwdArgs, const char **kwdlist, PyObject **unused,
+ const char *fmt, ...);
+static int sip_api_parse_pair(PyObject **parseErrp, PyObject *sipArg0,
+ PyObject *sipArg1, const char *fmt, ...);
+static void sip_api_no_function(PyObject *parseErr, const char *func,
+ const char *doc);
+static void sip_api_no_method(PyObject *parseErr, const char *scope,
+ const char *method, const char *doc);
+static void sip_api_abstract_method(const char *classname, const char *method);
+static void sip_api_bad_class(const char *classname);
+static void *sip_api_get_complex_cpp_ptr(sipSimpleWrapper *sw);
+static PyObject *sip_api_is_py_method(sip_gilstate_t *gil, char *pymc,
+ sipSimpleWrapper *sipSelf, const char *cname, const char *mname);
+static void sip_api_call_hook(const char *hookname);
+static void sip_api_raise_unknown_exception(void);
+static void sip_api_raise_type_exception(const sipTypeDef *td, void *ptr);
+static int sip_api_add_type_instance(PyObject *dict, const char *name,
+ void *cppPtr, const sipTypeDef *td);
+static sipErrorState sip_api_bad_callable_arg(int arg_nr, PyObject *arg);
+static void sip_api_bad_operator_arg(PyObject *self, PyObject *arg,
+ sipPySlotType st);
+static PyObject *sip_api_pyslot_extend(sipExportedModuleDef *mod,
+ sipPySlotType st, const sipTypeDef *td, PyObject *arg0,
+ PyObject *arg1);
+static void sip_api_add_delayed_dtor(sipSimpleWrapper *w);
+static unsigned long sip_api_long_as_unsigned_long(PyObject *o);
+static int sip_api_export_symbol(const char *name, void *sym);
+static void *sip_api_import_symbol(const char *name);
+static const sipTypeDef *sip_api_find_type(const char *type);
+static sipWrapperType *sip_api_find_class(const char *type);
+static const sipMappedType *sip_api_find_mapped_type(const char *type);
+static PyTypeObject *sip_api_find_named_enum(const char *type);
+static char sip_api_bytes_as_char(PyObject *obj);
+static const char *sip_api_bytes_as_string(PyObject *obj);
+static char sip_api_string_as_ascii_char(PyObject *obj);
+static const char *sip_api_string_as_ascii_string(PyObject **obj);
+static char sip_api_string_as_latin1_char(PyObject *obj);
+static const char *sip_api_string_as_latin1_string(PyObject **obj);
+static char sip_api_string_as_utf8_char(PyObject *obj);
+static const char *sip_api_string_as_utf8_string(PyObject **obj);
+#if defined(HAVE_WCHAR_H)
+static wchar_t sip_api_unicode_as_wchar(PyObject *obj);
+static wchar_t *sip_api_unicode_as_wstring(PyObject *obj);
+#else
+static int sip_api_unicode_as_wchar(PyObject *obj);
+static int *sip_api_unicode_as_wstring(PyObject *obj);
+#endif
+static void sip_api_transfer_break(PyObject *self);
+static int sip_api_deprecated(const char *classname, const char *method);
+static int sip_api_register_py_type(PyTypeObject *supertype);
+static PyObject *sip_api_convert_from_enum(int eval, const sipTypeDef *td);
+static const sipTypeDef *sip_api_type_from_py_type_object(PyTypeObject *py_type);
+static const sipTypeDef *sip_api_type_scope(const sipTypeDef *td);
+static const char *sip_api_resolve_typedef(const char *name);
+static int sip_api_register_attribute_getter(const sipTypeDef *td,
+ sipAttrGetterFunc getter);
+static void sip_api_clear_any_slot_reference(sipSlot *slot);
+static int sip_api_visit_slot(sipSlot *slot, visitproc visit, void *arg);
+static void sip_api_keep_reference(PyObject *self, int key, PyObject *obj);
+static void sip_api_add_exception(sipErrorState es, PyObject **parseErrp);
+
+
+/*
+ * The data structure that represents the SIP API.
+ */
+static const sipAPIDef sip_api = {
+ /* This must be first. */
+ sip_api_export_module,
+ /*
+ * The following are part of the public API.
+ */
+ (PyTypeObject *)&sipSimpleWrapper_Type,
+ (PyTypeObject *)&sipWrapper_Type,
+ &sipWrapperType_Type,
+ &sipVoidPtr_Type,
+
+ sip_api_bad_catcher_result,
+ sip_api_bad_length_for_slice,
+ sip_api_build_result,
+ sip_api_call_method,
+ sip_api_connect_rx,
+ sip_api_convert_from_sequence_index,
+ sip_api_can_convert_to_type,
+ sip_api_convert_to_type,
+ sip_api_force_convert_to_type,
+ sip_api_can_convert_to_enum,
+ sip_api_release_type,
+ sip_api_convert_from_type,
+ sip_api_convert_from_new_type,
+ sip_api_convert_from_enum,
+ sip_api_get_state,
+ sip_api_disconnect_rx,
+ sip_api_free,
+ sip_api_get_pyobject,
+ sip_api_malloc,
+ sip_api_parse_result,
+ sip_api_trace,
+ sip_api_transfer_back,
+ sip_api_transfer_to,
+ sip_api_transfer_break,
+ sip_api_long_as_unsigned_long,
+ sip_api_convert_from_void_ptr,
+ sip_api_convert_from_const_void_ptr,
+ sip_api_convert_from_void_ptr_and_size,
+ sip_api_convert_from_const_void_ptr_and_size,
+ sip_api_convert_to_void_ptr,
+ sip_api_export_symbol,
+ sip_api_import_symbol,
+ sip_api_find_type,
+ sip_api_register_py_type,
+ sip_api_type_from_py_type_object,
+ sip_api_type_scope,
+ sip_api_resolve_typedef,
+ sip_api_register_attribute_getter,
+ sip_api_is_api_enabled,
+ sip_api_bad_callable_arg,
+ /*
+ * The following are deprecated parts of the public API.
+ */
+ sip_api_find_named_enum,
+ sip_api_find_mapped_type,
+ sip_api_find_class,
+ sip_api_map_int_to_class,
+ sip_api_map_string_to_class,
+ /*
+ * The following may be used by Qt support code but by no other handwritten
+ * code.
+ */
+ sip_api_free_sipslot,
+ sip_api_same_slot,
+ sip_api_convert_rx,
+ sip_api_invoke_slot,
+ sip_api_save_slot,
+ sip_api_clear_any_slot_reference,
+ sip_api_visit_slot,
+ /*
+ * The following are not part of the public API.
+ */
+ sip_api_init_module,
+ sip_api_parse_args,
+ sip_api_parse_pair,
+ sip_api_common_dtor,
+ sip_api_no_function,
+ sip_api_no_method,
+ sip_api_abstract_method,
+ sip_api_bad_class,
+ sip_api_get_cpp_ptr,
+ sip_api_get_complex_cpp_ptr,
+ sip_api_is_py_method,
+ sip_api_call_hook,
+ sip_api_start_thread,
+ sip_api_end_thread,
+ sip_api_raise_unknown_exception,
+ sip_api_raise_type_exception,
+ sip_api_add_type_instance,
+ sip_api_bad_operator_arg,
+ sip_api_pyslot_extend,
+ sip_api_add_delayed_dtor,
+ sip_api_bytes_as_char,
+ sip_api_bytes_as_string,
+ sip_api_string_as_ascii_char,
+ sip_api_string_as_ascii_string,
+ sip_api_string_as_latin1_char,
+ sip_api_string_as_latin1_string,
+ sip_api_string_as_utf8_char,
+ sip_api_string_as_utf8_string,
+ sip_api_unicode_as_wchar,
+ sip_api_unicode_as_wstring,
+ sip_api_deprecated,
+ sip_api_keep_reference,
+ sip_api_parse_kwd_args,
+ sip_api_add_exception
+};
+
+
+#define AUTO_DOCSTRING '\1' /* Marks an auto class docstring. */
+
+
+/*
+ * These are the format flags supported by argument parsers.
+ */
+#define FMT_AP_DEREF 0x01 /* The pointer will be dereferenced. */
+#define FMT_AP_TRANSFER 0x02 /* Implement /Transfer/. */
+#define FMT_AP_TRANSFER_BACK 0x04 /* Implement /TransferBack/. */
+#define FMT_AP_NO_CONVERTORS 0x08 /* Suppress any convertors. */
+#define FMT_AP_TRANSFER_THIS 0x10 /* Support for /TransferThis/. */
+
+
+/*
+ * These are the format flags supported by result parsers. Deprecated values
+ * have a _DEPR suffix.
+ */
+#define FMT_RP_DEREF 0x01 /* The pointer will be dereferenced. */
+#define FMT_RP_FACTORY 0x02 /* /Factory/ or /TransferBack/. */
+#define FMT_RP_MAKE_COPY 0x04 /* Return a copy of the value. */
+#define FMT_RP_NO_STATE_DEPR 0x04 /* Don't return the C/C++ state. */
+
+
+/*
+ * The different reasons for failing to parse an overload. These include
+ * internal (i.e. non-user) errors.
+ */
+typedef enum {
+ Ok, Unbound, TooFew, TooMany, UnknownKeyword, Duplicate, WrongType, Raised,
+ KeywordNotString, Exception
+} sipParseFailureReason;
+
+
+/*
+ * The description of a failure to parse an overload because of a user error.
+ */
+typedef struct _sipParseFailure {
+ sipParseFailureReason reason; /* The reason for the failure. */
+ const char *detail_str; /* The detail if a string. */
+ PyObject *detail_obj; /* The detail if a Python object. */
+ int arg_nr; /* The wrong positional argument. */
+ const char *arg_name; /* The wrong keyword argument. */
+} sipParseFailure;
+
+
+/*
+ * An entry in a linked list of name/symbol pairs.
+ */
+typedef struct _sipSymbol {
+ const char *name; /* The name. */
+ void *symbol; /* The symbol. */
+ struct _sipSymbol *next; /* The next in the list. */
+} sipSymbol;
+
+
+/*
+ * An entry in a linked list of Python objects.
+ */
+typedef struct _sipPyObject {
+ PyObject *object; /* The Python object. */
+ struct _sipPyObject *next; /* The next in the list. */
+} sipPyObject;
+
+
+/*
+ * An entry in the linked list of attribute getters.
+ */
+typedef struct _sipAttrGetter {
+ PyTypeObject *type; /* The Python type being handled. */
+ sipAttrGetterFunc getter; /* The getter. */
+ struct _sipAttrGetter *next; /* The next in the list. */
+} sipAttrGetter;
+
+
+/*****************************************************************************
+ * The structures to support a Python type to hold a named enum.
+ *****************************************************************************/
+
+static PyObject *sipEnumType_alloc(PyTypeObject *self, SIP_SSIZE_T nitems);
+
+/*
+ * The type data structure. We inherit everything from the standard Python
+ * metatype and the size of the type object created is increased to accomodate
+ * the extra information we associate with a named enum type.
+ */
+static PyTypeObject sipEnumType_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "sip.enumtype", /* tp_name */
+ sizeof (sipEnumTypeObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved (Python v3), tp_compare (Python v2) */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ sipEnumType_alloc, /* tp_alloc */
+ 0, /* tp_new */
+ 0, /* tp_free */
+};
+
+
+sipQtAPI *sipQtSupport = NULL;
+sipTypeDef *sipQObjectType;
+
+
+/*
+ * Various strings as Python objects created as and when needed.
+ */
+static PyObject *licenseName = NULL;
+static PyObject *licenseeName = NULL;
+static PyObject *typeName = NULL;
+static PyObject *timestampName = NULL;
+static PyObject *signatureName = NULL;
+
+static sipObjectMap cppPyMap; /* The C/C++ to Python map. */
+static sipExportedModuleDef *moduleList = NULL; /* List of registered modules. */
+static unsigned traceMask = 0; /* The current trace mask. */
+
+static sipTypeDef *currentType = NULL; /* The type being created. */
+
+static PyObject *type_unpickler; /* The type unpickler function. */
+static PyObject *enum_unpickler; /* The enum unpickler function. */
+static sipSymbol *sipSymbolList = NULL; /* The list of published symbols. */
+static sipAttrGetter *sipAttrGetters = NULL; /* The list of attribute getters. */
+static sipPyObject *sipRegisteredPyTypes = NULL; /* Registered Python types. */
+static PyInterpreterState *sipInterpreter = NULL; /* The interpreter. */
+
+
+static void addClassSlots(sipWrapperType *wt, sipClassTypeDef *ctd);
+static void addTypeSlots(PyHeapTypeObject *heap_to, sipPySlotDef *slots);
+static void *findSlot(PyObject *self, sipPySlotType st);
+static void *findSlotInType(sipPySlotDef *psd, sipPySlotType st);
+static int objobjargprocSlot(PyObject *self, PyObject *arg1, PyObject *arg2,
+ sipPySlotType st);
+static int ssizeobjargprocSlot(PyObject *self, SIP_SSIZE_T arg1,
+ PyObject *arg2, sipPySlotType st);
+static PyObject *buildObject(PyObject *tup, const char *fmt, va_list va);
+static int parseKwdArgs(PyObject **parseErrp, PyObject *sipArgs,
+ PyObject *sipKwdArgs, const char **kwdlist, PyObject **unused,
+ const char *fmt, va_list va_orig);
+static int parsePass1(PyObject **parseErrp, sipSimpleWrapper **selfp,
+ int *selfargp, PyObject *sipArgs, PyObject *sipKwdArgs,
+ const char **kwdlist, PyObject **unused, const char *fmt, va_list va);
+static int parsePass2(sipSimpleWrapper *self, int selfarg, PyObject *sipArgs,
+ PyObject *sipKwdArgs, const char **kwdlist, const char *fmt,
+ va_list va);
+static PyObject *signature_FromDocstring(const char *doc, SIP_SSIZE_T line);
+static PyObject *detail_FromFailure(PyObject *failure_obj);
+static int isQObject(PyObject *obj);
+static int canConvertFromSequence(PyObject *seq, const sipTypeDef *td);
+static int convertFromSequence(PyObject *seq, const sipTypeDef *td,
+ void **array, SIP_SSIZE_T *nr_elem);
+static PyObject *convertToSequence(void *array, SIP_SSIZE_T nr_elem,
+ const sipTypeDef *td);
+static int getSelfFromArgs(sipTypeDef *td, PyObject *args, int argnr,
+ sipSimpleWrapper **selfp);
+static PyObject *createEnumMember(sipTypeDef *td, sipEnumMemberDef *enm);
+static int compareTypedefName(const void *key, const void *el);
+static int checkPointer(void *ptr);
+static void *cast_cpp_ptr(void *ptr, PyTypeObject *src_type,
+ const sipTypeDef *dst_type);
+static void finalise(void);
+static PyObject *getDefaultBases(void);
+static PyObject *getScopeDict(sipTypeDef *td, PyObject *mod_dict,
+ sipExportedModuleDef *client);
+static PyObject *createContainerType(sipContainerDef *cod, sipTypeDef *td,
+ PyObject *bases, PyObject *metatype, PyObject *mod_dict,
+ sipExportedModuleDef *client);
+static int createClassType(sipExportedModuleDef *client, sipClassTypeDef *ctd,
+ PyObject *mod_dict);
+static int createMappedType(sipExportedModuleDef *client,
+ sipMappedTypeDef *mtd, PyObject *mod_dict);
+static sipExportedModuleDef *getModule(PyObject *mname_obj);
+static PyObject *pickle_type(PyObject *obj, PyObject *);
+static PyObject *unpickle_type(PyObject *, PyObject *args);
+static PyObject *pickle_enum(PyObject *obj, PyObject *);
+static PyObject *unpickle_enum(PyObject *, PyObject *args);
+static int setReduce(PyTypeObject *type, PyMethodDef *pickler);
+static int createEnumType(sipExportedModuleDef *client, sipEnumTypeDef *etd,
+ PyObject *mod_dict);
+static PyObject *createTypeDict(PyObject *mname);
+static sipExportedModuleDef *getTypeModule(const sipEncodedTypeDef *enc,
+ sipExportedModuleDef *em);
+static sipTypeDef *getGeneratedType(const sipEncodedTypeDef *enc,
+ sipExportedModuleDef *em);
+static const sipTypeDef *convertSubClass(const sipTypeDef *td, void **cppPtr);
+static void *getPtrTypeDef(sipSimpleWrapper *self,
+ const sipClassTypeDef **ctd);
+static int addInstances(PyObject *dict, sipInstancesDef *id);
+static int addVoidPtrInstances(PyObject *dict, sipVoidPtrInstanceDef *vi);
+static int addCharInstances(PyObject *dict, sipCharInstanceDef *ci);
+static int addStringInstances(PyObject *dict, sipStringInstanceDef *si);
+static int addIntInstances(PyObject *dict, sipIntInstanceDef *ii);
+static int addLongInstances(PyObject *dict, sipLongInstanceDef *li);
+static int addUnsignedLongInstances(PyObject *dict,
+ sipUnsignedLongInstanceDef *uli);
+static int addLongLongInstances(PyObject *dict, sipLongLongInstanceDef *lli);
+static int addUnsignedLongLongInstances(PyObject *dict,
+ sipUnsignedLongLongInstanceDef *ulli);
+static int addDoubleInstances(PyObject *dict, sipDoubleInstanceDef *di);
+static int addTypeInstances(PyObject *dict, sipTypeInstanceDef *ti);
+static int addSingleTypeInstance(PyObject *dict, const char *name,
+ void *cppPtr, const sipTypeDef *td, int initflags);
+static int addLicense(PyObject *dict, sipLicenseDef *lc);
+static PyObject *cast(PyObject *self, PyObject *args);
+static PyObject *callDtor(PyObject *self, PyObject *args);
+static PyObject *dumpWrapper(PyObject *self, PyObject *args);
+static PyObject *isDeleted(PyObject *self, PyObject *args);
+static PyObject *isPyOwned(PyObject *self, PyObject *args);
+static PyObject *setDeleted(PyObject *self, PyObject *args);
+static PyObject *setTraceMask(PyObject *self, PyObject *args);
+static PyObject *wrapInstance(PyObject *self, PyObject *args);
+static PyObject *unwrapInstance(PyObject *self, PyObject *args);
+static PyObject *transferBack(PyObject *self, PyObject *args);
+static PyObject *transferTo(PyObject *self, PyObject *args);
+static void print_object(const char *label, PyObject *obj);
+static void addToParent(sipWrapper *self, sipWrapper *owner);
+static void removeFromParent(sipWrapper *self);
+static void release(void *addr, const sipTypeDef *td, int state);
+static void callPyDtor(sipSimpleWrapper *self);
+static int parseBytes_AsCharArray(PyObject *obj, const char **ap,
+ SIP_SSIZE_T *aszp);
+static int parseBytes_AsChar(PyObject *obj, char *ap);
+static int parseBytes_AsString(PyObject *obj, const char **ap);
+static int parseString_AsASCIIChar(PyObject *obj, char *ap);
+static PyObject *parseString_AsASCIIString(PyObject *obj, const char **ap);
+static int parseString_AsLatin1Char(PyObject *obj, char *ap);
+static PyObject *parseString_AsLatin1String(PyObject *obj, const char **ap);
+static int parseString_AsUTF8Char(PyObject *obj, char *ap);
+static PyObject *parseString_AsUTF8String(PyObject *obj, const char **ap);
+static int parseString_AsEncodedChar(PyObject *bytes, PyObject *obj, char *ap);
+static PyObject *parseString_AsEncodedString(PyObject *bytes, PyObject *obj,
+ const char **ap);
+#if defined(HAVE_WCHAR_H)
+static int parseWCharArray(PyObject *obj, wchar_t **ap, SIP_SSIZE_T *aszp);
+static int convertToWCharArray(PyObject *obj, wchar_t **ap, SIP_SSIZE_T *aszp);
+static int parseWChar(PyObject *obj, wchar_t *ap);
+static int convertToWChar(PyObject *obj, wchar_t *ap);
+static int parseWCharString(PyObject *obj, wchar_t **ap);
+static int convertToWCharString(PyObject *obj, wchar_t **ap);
+#else
+static void raiseNoWChar();
+#endif
+static void *getComplexCppPtr(sipSimpleWrapper *w, const sipTypeDef *td);
+static PyObject *findPyType(const char *name);
+static int addPyObjectToList(sipPyObject **head, PyObject *object);
+static PyObject *getDictFromObject(PyObject *obj);
+static void forgetObject(sipSimpleWrapper *sw);
+static int add_lazy_container_attrs(sipTypeDef *td, sipContainerDef *cod,
+ PyObject *dict);
+static int add_lazy_attrs(sipTypeDef *td);
+static int add_all_lazy_attrs(sipTypeDef *td);
+static int objectify(const char *s, PyObject **objp);
+static void add_failure(PyObject **parseErrp, sipParseFailure *failure);
+static PyObject *bad_type_str(int arg_nr, PyObject *arg);
+
+
+/*
+ * The Python module initialisation function.
+ */
+#if PY_MAJOR_VERSION >= 3
+#define SIP_MODULE_ENTRY PyInit_sip
+#define SIP_MODULE_TYPE PyObject *
+#define SIP_MODULE_DISCARD(m) Py_DECREF(m)
+#define SIP_FATAL(s) return NULL
+#define SIP_MODULE_RETURN(m) return (m)
+#else
+#define SIP_MODULE_ENTRY initsip
+#define SIP_MODULE_TYPE void
+#define SIP_MODULE_DISCARD(m)
+#define SIP_FATAL(s) Py_FatalError(s)
+#define SIP_MODULE_RETURN(m)
+#endif
+
+#if defined(SIP_STATIC_MODULE)
+SIP_MODULE_TYPE SIP_MODULE_ENTRY(void)
+#else
+PyMODINIT_FUNC SIP_MODULE_ENTRY(void)
+#endif
+{
+ static PyMethodDef methods[] = {
+ {"cast", cast, METH_VARARGS, NULL},
+ {"delete", callDtor, METH_VARARGS, NULL},
+ {"dump", dumpWrapper, METH_VARARGS, NULL},
+ {"getapi", sipGetAPI, METH_VARARGS, NULL},
+ {"isdeleted", isDeleted, METH_VARARGS, NULL},
+ {"ispyowned", isPyOwned, METH_VARARGS, NULL},
+ {"setapi", sipSetAPI, METH_VARARGS, NULL},
+ {"setdeleted", setDeleted, METH_VARARGS, NULL},
+ {"settracemask", setTraceMask, METH_VARARGS, NULL},
+ {"transferback", transferBack, METH_VARARGS, NULL},
+ {"transferto", transferTo, METH_VARARGS, NULL},
+ {"wrapinstance", wrapInstance, METH_VARARGS, NULL},
+ {"unwrapinstance", unwrapInstance, METH_VARARGS, NULL},
+ {"_unpickle_type", unpickle_type, METH_VARARGS, NULL},
+ {"_unpickle_enum", unpickle_enum, METH_VARARGS, NULL},
+ {NULL, NULL, 0, NULL}
+ };
+
+#if PY_MAJOR_VERSION >= 3
+ static PyModuleDef module_def = {
+ PyModuleDef_HEAD_INIT,
+ "sip", /* m_name */
+ NULL, /* m_doc */
+ -1, /* m_size */
+ methods, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL, /* m_free */
+ };
+#endif
+
+ int rc;
+ PyObject *mod, *mod_dict, *obj;
+
+#ifdef WITH_THREAD
+ PyEval_InitThreads();
+#endif
+
+ /* Initialise the types. */
+ sipWrapperType_Type.tp_base = &PyType_Type;
+
+ if (PyType_Ready(&sipWrapperType_Type) < 0)
+ SIP_FATAL("sip: Failed to initialise sip.wrappertype type");
+
+ if (PyType_Ready((PyTypeObject *)&sipSimpleWrapper_Type) < 0)
+ SIP_FATAL("sip: Failed to initialise sip.simplewrapper type");
+
+ if (sip_api_register_py_type((PyTypeObject *)&sipSimpleWrapper_Type) < 0)
+ SIP_FATAL("sip: Failed to register sip.simplewrapper type");
+
+#if defined(STACKLESS)
+ sipWrapper_Type.super.tp_base = (PyTypeObject *)&sipSimpleWrapper_Type;
+#elif PY_VERSION_HEX >= 0x02050000
+ sipWrapper_Type.super.ht_type.tp_base = (PyTypeObject *)&sipSimpleWrapper_Type;
+#else
+ sipWrapper_Type.super.type.tp_base = (PyTypeObject *)&sipSimpleWrapper_Type;
+#endif
+
+ if (PyType_Ready((PyTypeObject *)&sipWrapper_Type) < 0)
+ SIP_FATAL("sip: Failed to initialise sip.wrapper type");
+
+ if (PyType_Ready(&sipMethodDescr_Type) < 0)
+ SIP_FATAL("sip: Failed to initialise sip.methoddescriptor type");
+
+ if (PyType_Ready(&sipVariableDescr_Type) < 0)
+ SIP_FATAL("sip: Failed to initialise sip.variabledescriptor type");
+
+ sipEnumType_Type.tp_base = &PyType_Type;
+
+ if (PyType_Ready(&sipEnumType_Type) < 0)
+ SIP_FATAL("sip: Failed to initialise sip.enumtype type");
+
+ if (PyType_Ready(&sipVoidPtr_Type) < 0)
+ SIP_FATAL("sip: Failed to initialise sip.voidptr type");
+
+#if PY_MAJOR_VERSION >= 3
+ mod = PyModule_Create(&module_def);
+#else
+ mod = Py_InitModule("sip", methods);
+#endif
+
+ if (mod == NULL)
+ SIP_FATAL("sip: Failed to intialise sip module");
+
+ mod_dict = PyModule_GetDict(mod);
+
+ /* Get a reference to the pickle helpers. */
+ type_unpickler = PyDict_GetItemString(mod_dict, "_unpickle_type");
+ enum_unpickler = PyDict_GetItemString(mod_dict, "_unpickle_enum");
+
+ if (type_unpickler == NULL || enum_unpickler == NULL)
+ {
+ SIP_MODULE_DISCARD(mod);
+ SIP_FATAL("sip: Failed to get pickle helpers");
+ }
+
+ /* Publish the SIP API. */
+#if defined(SIP_USE_PYCAPSULE)
+ obj = PyCapsule_New((void *)&sip_api, "sip._C_API", NULL);
+#else
+ obj = PyCObject_FromVoidPtr((void *)&sip_api, NULL);
+#endif
+
+ if (obj == NULL)
+ {
+ SIP_MODULE_DISCARD(mod);
+ SIP_FATAL("sip: Failed to create _C_API object");
+ }
+
+ rc = PyDict_SetItemString(mod_dict, "_C_API", obj);
+ Py_DECREF(obj);
+
+ if (rc < 0)
+ {
+ SIP_MODULE_DISCARD(mod);
+ SIP_FATAL("sip: Failed to add _C_API object to module dictionary");
+ }
+
+ /* Add the SIP version number, but don't worry about errors. */
+#if PY_MAJOR_VERSION >= 3
+ obj = PyLong_FromLong(SIP_VERSION);
+#else
+ obj = PyInt_FromLong(SIP_VERSION);
+#endif
+
+ if (obj != NULL)
+ {
+ PyDict_SetItemString(mod_dict, "SIP_VERSION", obj);
+ Py_DECREF(obj);
+ }
+
+#if PY_MAJOR_VERSION >= 3
+ obj = PyUnicode_FromString(SIP_VERSION_STR);
+#else
+ obj = PyString_FromString(SIP_VERSION_STR);
+#endif
+
+ if (obj != NULL)
+ {
+ PyDict_SetItemString(mod_dict, "SIP_VERSION_STR", obj);
+ Py_DECREF(obj);
+ }
+
+ /* Add the type objects, but don't worry about errors. */
+ PyDict_SetItemString(mod_dict, "wrappertype",
+ (PyObject *)&sipWrapperType_Type);
+ PyDict_SetItemString(mod_dict, "simplewrapper",
+ (PyObject *)&sipSimpleWrapper_Type);
+ PyDict_SetItemString(mod_dict, "wrapper", (PyObject *)&sipWrapper_Type);
+ PyDict_SetItemString(mod_dict, "voidptr", (PyObject *)&sipVoidPtr_Type);
+
+ /* Initialise the module if it hasn't already been done. */
+ if (sipInterpreter == NULL)
+ {
+ Py_AtExit(finalise);
+
+ /* Initialise the object map. */
+ sipOMInit(&cppPyMap);
+
+ sipQtSupport = NULL;
+
+ /*
+ * Get the current interpreter. This will be shared between all
+ * threads.
+ */
+ sipInterpreter = PyThreadState_Get()->interp;
+ }
+
+ SIP_MODULE_RETURN(mod);
+}
+
+
+/*
+ * Display a printf() style message to stderr according to the current trace
+ * mask.
+ */
+static void sip_api_trace(unsigned mask, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap,fmt);
+
+ if (mask & traceMask)
+ vfprintf(stderr, fmt, ap);
+
+ va_end(ap);
+}
+
+
+/*
+ * Set the trace mask.
+ */
+static PyObject *setTraceMask(PyObject *self, PyObject *args)
+{
+ unsigned new_mask;
+
+ if (PyArg_ParseTuple(args, "I:settracemask", &new_mask))
+ {
+ traceMask = new_mask;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ return NULL;
+}
+
+
+/*
+ * Dump various bits of potentially useful information to stdout.
+ */
+static PyObject *dumpWrapper(PyObject *self, PyObject *args)
+{
+ sipSimpleWrapper *sw;
+
+ if (PyArg_ParseTuple(args, "O!:dump", &sipSimpleWrapper_Type, &sw))
+ {
+ print_object(NULL, (PyObject *)sw);
+
+#if PY_VERSION_HEX >= 0x02050000
+ printf(" Reference count: %" PY_FORMAT_SIZE_T "d\n", Py_REFCNT(sw));
+#else
+ printf(" Reference count: %d\n", Py_REFCNT(sw));
+#endif
+ printf(" Address of wrapped object: %p\n", sipGetAddress(sw));
+ printf(" To be destroyed by: %s\n", (sipIsPyOwned(sw) ? "Python" : "C/C++"));
+ printf(" Derived class?: %s\n", (sipIsDerived(sw) ? "yes" : "no"));
+
+ if (PyObject_TypeCheck((PyObject *)sw, (PyTypeObject *)&sipWrapper_Type))
+ {
+ sipWrapper *w = (sipWrapper *)sw;
+
+ print_object("Parent wrapper", (PyObject *)w->parent);
+ print_object("Next sibling wrapper", (PyObject *)w->sibling_next);
+ print_object("Previous sibling wrapper",
+ (PyObject *)w->sibling_prev);
+ print_object("First child wrapper", (PyObject *)w->first_child);
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ return NULL;
+}
+
+
+/*
+ * Write a reference to a wrapper to stdout.
+ */
+static void print_object(const char *label, PyObject *obj)
+{
+ if (label != NULL)
+ printf(" %s: ", label);
+
+ if (obj != NULL)
+ PyObject_Print(obj, stdout, 0);
+ else
+ printf("NULL");
+
+ printf("\n");
+}
+
+
+/*
+ * Transfer the ownership of an instance to C/C++.
+ */
+static PyObject *transferTo(PyObject *self, PyObject *args)
+{
+ PyObject *w, *owner;
+
+ if (PyArg_ParseTuple(args, "O!O:transferto", &sipWrapper_Type, &w, &owner))
+ {
+ if (owner == Py_None)
+ owner = NULL;
+ else if (PyObject_TypeCheck(owner, (PyTypeObject *)&sipWrapper_Type))
+ {
+ PyErr_Format(PyExc_TypeError, "transferto() argument 2 must be sip.wrapper, not %s", Py_TYPE(owner)->tp_name);
+ return NULL;
+ }
+
+ sip_api_transfer_to(w, owner);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ return NULL;
+}
+
+
+/*
+ * Transfer the ownership of an instance to Python.
+ */
+static PyObject *transferBack(PyObject *self, PyObject *args)
+{
+ PyObject *w;
+
+ if (PyArg_ParseTuple(args, "O!:transferback", &sipWrapper_Type, &w))
+ {
+ sip_api_transfer_back(w);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ return NULL;
+}
+
+
+/*
+ * Cast an instance to one of it's sub or super-classes by returning a new
+ * Python object with the superclass type wrapping the same C++ instance.
+ */
+static PyObject *cast(PyObject *self, PyObject *args)
+{
+ sipSimpleWrapper *sw;
+ sipWrapperType *wt;
+ const sipTypeDef *td;
+ void *addr;
+ PyTypeObject *ft, *tt;
+
+ if (!PyArg_ParseTuple(args, "O!O!:cast", &sipSimpleWrapper_Type, &sw, &sipWrapperType_Type, &wt))
+ return NULL;
+
+ ft = Py_TYPE(sw);
+ tt = (PyTypeObject *)wt;
+
+ if (ft == tt || PyType_IsSubtype(tt, ft))
+ td = NULL;
+ else if (PyType_IsSubtype(ft, tt))
+ td = wt->type;
+ else
+ {
+ PyErr_SetString(PyExc_TypeError, "argument 1 of sip.cast() must be an instance of a sub or super-type of argument 2");
+ return NULL;
+ }
+
+ if ((addr = sip_api_get_cpp_ptr(sw, td)) == NULL)
+ return NULL;
+
+ /*
+ * We don't put this new object into the map so that the original object is
+ * always found. It would also totally confuse the map logic.
+ */
+ return sipWrapSimpleInstance(addr, wt->type, NULL, (sw->flags | SIP_NOT_IN_MAP) & ~SIP_PY_OWNED);
+}
+
+
+/*
+ * Call an instance's dtor.
+ */
+static PyObject *callDtor(PyObject *self, PyObject *args)
+{
+ sipSimpleWrapper *sw;
+ void *addr;
+ const sipClassTypeDef *ctd;
+
+ if (!PyArg_ParseTuple(args, "O!:delete", &sipSimpleWrapper_Type, &sw))
+ return NULL;
+
+ addr = getPtrTypeDef(sw, &ctd);
+
+ if (checkPointer(addr) < 0)
+ return NULL;
+
+ if (PyObject_TypeCheck((PyObject *)sw, (PyTypeObject *)&sipWrapper_Type))
+ {
+ /*
+ * Transfer ownership to C++ so we don't try to release it again when
+ * the Python object is garbage collected.
+ */
+ removeFromParent((sipWrapper *)sw);
+ sipResetPyOwned(sw);
+ }
+
+ release(addr, (const sipTypeDef *)ctd, sw->flags);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+/*
+ * Check if an instance still exists without raising an exception.
+ */
+static PyObject *isDeleted(PyObject *self, PyObject *args)
+{
+ sipSimpleWrapper *sw;
+ PyObject *res;
+
+ if (!PyArg_ParseTuple(args, "O!:isdeleted", &sipSimpleWrapper_Type, &sw))
+ return NULL;
+
+ res = (sipGetAddress(sw) == NULL ? Py_True : Py_False);
+
+ Py_INCREF(res);
+ return res;
+}
+
+
+/*
+ * Check if an instance is owned by Python or C/C++.
+ */
+static PyObject *isPyOwned(PyObject *self, PyObject *args)
+{
+ sipSimpleWrapper *sw;
+ PyObject *res;
+
+ if (!PyArg_ParseTuple(args, "O!:ispyowned", &sipSimpleWrapper_Type, &sw))
+ return NULL;
+
+ res = (sipIsPyOwned(sw) ? Py_True : Py_False);
+
+ Py_INCREF(res);
+ return res;
+}
+
+
+/*
+ * Mark an instance as having been deleted.
+ */
+static PyObject *setDeleted(PyObject *self, PyObject *args)
+{
+ sipSimpleWrapper *sw;
+
+ if (!PyArg_ParseTuple(args, "O!:setdeleted", &sipSimpleWrapper_Type, &sw))
+ return NULL;
+
+ if (PyObject_TypeCheck((PyObject *)sw, (PyTypeObject *)&sipWrapper_Type))
+ {
+ /*
+ * Transfer ownership to C++ so we don't try to release it when the
+ * Python object is garbage collected.
+ */
+ removeFromParent((sipWrapper *)sw);
+ sipResetPyOwned(sw);
+ }
+
+ sw->u.cppPtr = NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+/*
+ * Unwrap an instance.
+ */
+static PyObject *unwrapInstance(PyObject *self, PyObject *args)
+{
+ sipSimpleWrapper *sw;
+
+ if (PyArg_ParseTuple(args, "O!:unwrapinstance", &sipSimpleWrapper_Type, &sw))
+ {
+ void *addr;
+
+ /*
+ * We just get the pointer but don't try and cast it (which isn't
+ * needed and wouldn't work with the way casts are currently
+ * implemented if we are unwrapping something derived from a wrapped
+ * class).
+ */
+ if ((addr = sip_api_get_cpp_ptr(sw, NULL)) == NULL)
+ return NULL;
+
+ return PyLong_FromVoidPtr(addr);
+ }
+
+ return NULL;
+}
+
+
+/*
+ * Wrap an instance.
+ */
+static PyObject *wrapInstance(PyObject *self, PyObject *args)
+{
+ unsigned long addr;
+ sipWrapperType *wt;
+
+ if (PyArg_ParseTuple(args, "kO!:wrapinstance", &addr, &sipWrapperType_Type, &wt))
+ return sip_api_convert_from_type((void *)addr, wt->type, NULL);
+
+ return NULL;
+}
+
+
+/*
+ * Register a client module. A negative value is returned and an exception
+ * raised if there was an error.
+ */
+static int sip_api_export_module(sipExportedModuleDef *client,
+ unsigned api_major, unsigned api_minor, void *unused)
+{
+ sipExportedModuleDef *em;
+ const char *full_name = sipNameOfModule(client);
+
+ /* Check that we can support it. */
+
+ if (api_major != SIP_API_MAJOR_NR || api_minor > SIP_API_MINOR_NR)
+ {
+#if SIP_API_MINOR_NR > 0
+ PyErr_Format(PyExc_RuntimeError,
+ "the sip module implements API v%d.0 to v%d.%d but the %s module requires API v%d.%d",
+ SIP_API_MAJOR_NR, SIP_API_MAJOR_NR, SIP_API_MINOR_NR,
+ full_name, api_major, api_minor);
+#else
+ PyErr_Format(PyExc_RuntimeError,
+ "the sip module implements API v%d.0 but the %s module requires API v%d.%d",
+ SIP_API_MAJOR_NR, full_name, api_major, api_minor);
+#endif
+
+ return -1;
+ }
+
+ /* Import any required modules. */
+ if (client->em_imports != NULL)
+ {
+ sipImportedModuleDef *im = client->em_imports;
+
+ while (im->im_name != NULL)
+ {
+ PyObject *mod;
+
+ if ((mod = PyImport_ImportModule(im->im_name)) == NULL)
+ return -1;
+
+ for (em = moduleList; em != NULL; em = em->em_next)
+ if (strcmp(sipNameOfModule(em), im->im_name) == 0)
+ break;
+
+ if (em == NULL)
+ {
+ PyErr_Format(PyExc_RuntimeError,
+ "the %s module failed to register with the sip module",
+ im->im_name);
+
+ return -1;
+ }
+
+ /* Check the versions are compatible. */
+ if (im->im_version >= 0 || em->em_version >= 0)
+ if (im->im_version != em->em_version)
+ {
+ PyErr_Format(PyExc_RuntimeError,
+ "the %s module is version %d but the %s module requires version %d",
+ sipNameOfModule(em), em->em_version, full_name,
+ im->im_version);
+
+ return -1;
+ }
+
+ /* Save the imported module. */
+ im->im_module = em;
+
+ ++im;
+ }
+ }
+
+ for (em = moduleList; em != NULL; em = em->em_next)
+ {
+ /* SIP clients must have unique names. */
+ if (strcmp(sipNameOfModule(em), full_name) == 0)
+ {
+ PyErr_Format(PyExc_RuntimeError,
+ "the sip module has already registered a module called %s",
+ full_name);
+
+ return -1;
+ }
+
+ /* Only one module can claim to wrap QObject. */
+ if (em->em_qt_api != NULL && client->em_qt_api != NULL)
+ {
+ PyErr_Format(PyExc_RuntimeError,
+ "the %s and %s modules both wrap the QObject class",
+ full_name, sipNameOfModule(em));
+
+ return -1;
+ }
+ }
+
+ /* Convert the module name to an object. */
+#if PY_MAJOR_VERSION >= 3
+ client->em_nameobj = PyUnicode_FromString(full_name);
+#else
+ client->em_nameobj = PyString_FromString(full_name);
+#endif
+
+ if (client->em_nameobj == NULL)
+ return -1;
+
+ /* Add it to the list of client modules. */
+ client->em_next = moduleList;
+ moduleList = client;
+
+ return 0;
+}
+
+
+/*
+ * Initialise the contents of a client module. By this time anything that
+ * this depends on should have been initialised. A negative value is returned
+ * and an exception raised if there was an error.
+ */
+static int sip_api_init_module(sipExportedModuleDef *client,
+ PyObject *mod_dict)
+{
+ sipExportedModuleDef *em;
+ sipEnumMemberDef *emd;
+ int i;
+
+ /* Handle any API. */
+ if (sipInitAPI(client, mod_dict) < 0)
+ return -1;
+
+ /* Create the module's types. */
+ for (i = 0; i < client->em_nrtypes; ++i)
+ {
+ sipTypeDef *td = client->em_types[i];
+
+ /* Skip external classes. */
+ if (td == NULL)
+ continue;
+
+ /* Skip if already initialised. */
+ if (td->td_module != NULL)
+ continue;
+
+ /* If it is a stub then just set the module so we can get its name. */
+ if (sipTypeIsStub(td))
+ {
+ td->td_module = client;
+ continue;
+ }
+
+ if (sipTypeIsEnum(td))
+ {
+ sipEnumTypeDef *etd = (sipEnumTypeDef *)td;
+
+ if (td->td_version < 0 || sipIsRangeEnabled(client, td->td_version))
+ if (createEnumType(client, etd, mod_dict) < 0)
+ return -1;
+
+ /*
+ * Register the enum pickler for scoped enums (unscoped, ie. those
+ * not nested, don't need special treatment).
+ */
+ if (etd->etd_scope >= 0)
+ {
+ static PyMethodDef md = {
+ "_pickle_enum", pickle_enum, METH_NOARGS, NULL
+ };
+
+ if (setReduce(sipTypeAsPyTypeObject(td), &md) < 0)
+ return -1;
+ }
+ }
+ else if (sipTypeIsMapped(td))
+ {
+ sipMappedTypeDef *mtd = (sipMappedTypeDef *)td;
+
+ /* If there is a name then we need a namespace. */
+ if (mtd->mtd_container.cod_name >= 0)
+ {
+ if (createMappedType(client, mtd, mod_dict) < 0)
+ return -1;
+ }
+ else
+ {
+ td->td_module = client;
+ }
+ }
+ else
+ {
+ sipClassTypeDef *ctd = (sipClassTypeDef *)td;
+
+ /* See if this is a namespace extender. */
+ if (ctd->ctd_container.cod_name < 0)
+ {
+ sipTypeDef *real_nspace;
+ sipClassTypeDef **last;
+
+ ctd->ctd_base.td_module = client;
+
+ real_nspace = getGeneratedType(&ctd->ctd_container.cod_scope,
+ client);
+
+ /* Append this type to the real one. */
+ last = &((sipClassTypeDef *)real_nspace)->ctd_nsextender;
+
+ while (*last != NULL)
+ last = &(*last)->ctd_nsextender;
+
+ *last = ctd;
+
+ /*
+ * Save the real namespace type so that it is the correct scope
+ * for any enums or classes defined in this module.
+ */
+ client->em_types[i] = real_nspace;
+ }
+ else if (createClassType(client, ctd, mod_dict) < 0)
+ return -1;
+ }
+ }
+
+ /* Set any Qt support API. */
+ if (client->em_qt_api != NULL)
+ {
+ sipQtSupport = client->em_qt_api;
+ sipQObjectType = *sipQtSupport->qt_qobject;
+ }
+
+ /* Append any initialiser extenders to the relevant classes. */
+ if (client->em_initextend != NULL)
+ {
+ sipInitExtenderDef *ie = client->em_initextend;
+
+ while (ie->ie_extender != NULL)
+ {
+ sipTypeDef *td = getGeneratedType(&ie->ie_class, client);
+ int enabled;
+
+ if (ie->ie_api_range < 0)
+ enabled = TRUE;
+ else
+ enabled = sipIsRangeEnabled(td->td_module, ie->ie_api_range);
+
+ if (enabled)
+ {
+ sipWrapperType *wt = (sipWrapperType *)sipTypeAsPyTypeObject(td);
+
+ ie->ie_next = wt->iextend;
+ wt->iextend = ie;
+ }
+
+ ++ie;
+ }
+ }
+
+ /* Set the base class object for any sub-class convertors. */
+ if (client->em_convertors != NULL)
+ {
+ sipSubClassConvertorDef *scc = client->em_convertors;
+
+ while (scc->scc_convertor != NULL)
+ {
+ scc->scc_basetype = getGeneratedType(&scc->scc_base, client);
+
+ ++scc;
+ }
+ }
+
+ /* Create the module's enum members. */
+ for (emd = client->em_enummembers, i = 0; i < client->em_nrenummembers; ++i, ++emd)
+ {
+ PyObject *mo;
+
+ if ((mo = sip_api_convert_from_enum(emd->em_val, client->em_types[emd->em_enum])) == NULL)
+ return -1;
+
+ if (PyDict_SetItemString(mod_dict, emd->em_name, mo) < 0)
+ return -1;
+
+ Py_DECREF(mo);
+ }
+
+
+ /*
+ * Add any class static instances. We need to do this once all types are
+ * fully formed because of potential interdependencies.
+ */
+ for (i = 0; i < client->em_nrtypes; ++i)
+ {
+ sipTypeDef *td = client->em_types[i];
+
+ if (td != NULL && !sipTypeIsStub(td) && sipTypeIsClass(td))
+ if (addInstances((sipTypeAsPyTypeObject(td))->tp_dict, &((sipClassTypeDef *)td)->ctd_container.cod_instances) < 0)
+ return -1;
+ }
+
+ /* Add any global static instances. */
+ if (addInstances(mod_dict, &client->em_instances) < 0)
+ return -1;
+
+ /* Add any license. */
+ if (client->em_license != NULL && addLicense(mod_dict, client->em_license) < 0)
+ return -1;
+
+ /* See if the new module satisfies any outstanding external types. */
+ for (em = moduleList; em != NULL; em = em->em_next)
+ {
+ sipExternalTypeDef *etd;
+
+ if (em == client || em->em_external == NULL)
+ continue;
+
+ for (etd = em->em_external; etd->et_nr >= 0; ++etd)
+ {
+ if (etd->et_name == NULL)
+ continue;
+
+ for (i = 0; i < client->em_nrtypes; ++i)
+ {
+ sipTypeDef *td = client->em_types[i];
+
+ if (td != NULL && !sipTypeIsStub(td) && sipTypeIsClass(td))
+ {
+ const char *pyname = sipPyNameOfContainer(
+ &((sipClassTypeDef *)td)->ctd_container, td);
+
+ if (strcmp(etd->et_name, pyname) == 0)
+ {
+ em->em_types[etd->et_nr] = td;
+ etd->et_name = NULL;
+
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+/*
+ * Called by the interpreter to do any final clearing up, just in case the
+ * interpreter will re-start.
+ */
+static void finalise(void)
+{
+ sipExportedModuleDef *em;
+
+ /* Mark the Python API as unavailable. */
+ sipInterpreter = NULL;
+
+ /* Handle any delayed dtors. */
+ for (em = moduleList; em != NULL; em = em->em_next)
+ if (em->em_ddlist != NULL)
+ {
+ em->em_delayeddtors(em->em_ddlist);
+
+ /* Free the list. */
+ do
+ {
+ sipDelayedDtor *dd = em->em_ddlist;
+
+ em->em_ddlist = dd->dd_next;
+ sip_api_free(dd);
+ }
+ while (em->em_ddlist != NULL);
+ }
+
+ licenseName = NULL;
+ licenseeName = NULL;
+ typeName = NULL;
+ timestampName = NULL;
+ signatureName = NULL;
+
+ /* Release all memory we've allocated directly. */
+ sipOMFinalise(&cppPyMap);
+
+ /* Re-initialise those globals that (might) need it. */
+ moduleList = NULL;
+}
+
+
+/*
+ * Register the given Python type.
+ */
+static int sip_api_register_py_type(PyTypeObject *type)
+{
+ return addPyObjectToList(&sipRegisteredPyTypes, (PyObject *)type);
+}
+
+
+/*
+ * Find the registered type with the given name. Raise an exception if it
+ * couldn't be found.
+ */
+static PyObject *findPyType(const char *name)
+{
+ sipPyObject *po;
+
+ for (po = sipRegisteredPyTypes; po != NULL; po = po->next)
+ {
+ PyObject *type = po->object;
+
+ if (strcmp(((PyTypeObject *)type)->tp_name, name) == 0)
+ return type;
+ }
+
+ PyErr_Format(PyExc_RuntimeError, "%s is not a registered type", name);
+
+ return NULL;
+}
+
+
+/*
+ * Add a wrapped C/C++ pointer to the list of delayed dtors.
+ */
+static void sip_api_add_delayed_dtor(sipSimpleWrapper *sw)
+{
+ void *ptr;
+ const sipClassTypeDef *ctd;
+ sipExportedModuleDef *em;
+
+ if ((ptr = getPtrTypeDef(sw, &ctd)) == NULL)
+ return;
+
+ /* Find the defining module. */
+ for (em = moduleList; em != NULL; em = em->em_next)
+ {
+ int i;
+
+ for (i = 0; i < em->em_nrtypes; ++i)
+ if (em->em_types[i] == (const sipTypeDef *)ctd)
+ {
+ sipDelayedDtor *dd;
+
+ if ((dd = sip_api_malloc(sizeof (sipDelayedDtor))) == NULL)
+ return;
+
+ /* Add to the list. */
+ dd->dd_ptr = ptr;
+ dd->dd_name = sipPyNameOfContainer(&ctd->ctd_container,
+ (sipTypeDef *)ctd);
+ dd->dd_isderived = sipIsDerived(sw);
+ dd->dd_next = em->em_ddlist;
+
+ em->em_ddlist = dd;
+
+ return;
+ }
+ }
+}
+
+
+/*
+ * A wrapper around the Python memory allocater that will raise an exception if
+ * if the allocation fails.
+ */
+void *sip_api_malloc(size_t nbytes)
+{
+ void *mem;
+
+ if ((mem = PyMem_Malloc(nbytes)) == NULL)
+ PyErr_NoMemory();
+
+ return mem;
+}
+
+
+/*
+ * A wrapper around the Python memory de-allocater.
+ */
+void sip_api_free(void *mem)
+{
+ PyMem_Free(mem);
+}
+
+
+/*
+ * Extend a Python slot by looking in other modules to see if there is an
+ * extender function that can handle the arguments.
+ */
+static PyObject *sip_api_pyslot_extend(sipExportedModuleDef *mod,
+ sipPySlotType st, const sipTypeDef *td, PyObject *arg0,
+ PyObject *arg1)
+{
+ sipExportedModuleDef *em;
+
+ /* Go through each module. */
+ for (em = moduleList; em != NULL; em = em->em_next)
+ {
+ sipPySlotExtenderDef *ex;
+
+ /* Skip the module that couldn't handle the arguments. */
+ if (em == mod)
+ continue;
+
+ /* Skip if the module doesn't have any extenders. */
+ if (em->em_slotextend == NULL)
+ continue;
+
+ /* Go through each extender. */
+ for (ex = em->em_slotextend; ex->pse_func != NULL; ++ex)
+ {
+ PyObject *res;
+
+ /* Skip if not the right slot type. */
+ if (ex->pse_type != st)
+ continue;
+
+ /* Check against the type if one was given. */
+ if (td != NULL && td != getGeneratedType(&ex->pse_class, NULL))
+ continue;
+
+ PyErr_Clear();
+
+ res = ((binaryfunc)ex->pse_func)(arg0, arg1);
+
+ if (res != Py_NotImplemented)
+ return res;
+ }
+ }
+
+ /* The arguments couldn't handled anywhere. */
+ PyErr_Clear();
+
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+}
+
+
+/*
+ * Call the Python re-implementation of a C++ virtual.
+ */
+static PyObject *sip_api_call_method(int *isErr, PyObject *method,
+ const char *fmt, ...)
+{
+ PyObject *args, *res;
+ va_list va;
+
+ va_start(va,fmt);
+
+ if ((args = PyTuple_New(strlen(fmt))) != NULL && buildObject(args,fmt,va) != NULL)
+ res = PyEval_CallObject(method,args);
+ else
+ {
+ res = NULL;
+
+ if (isErr != NULL)
+ *isErr = TRUE;
+ }
+
+ Py_XDECREF(args);
+
+ va_end(va);
+
+ return res;
+}
+
+
+/*
+ * Build a result object based on a format string.
+ */
+static PyObject *sip_api_build_result(int *isErr, const char *fmt, ...)
+{
+ PyObject *res = NULL;
+ int badfmt, tupsz;
+ va_list va;
+
+ va_start(va,fmt);
+
+ /* Basic validation of the format string. */
+
+ badfmt = FALSE;
+
+ if (*fmt == '(')
+ {
+ char *ep;
+
+ if ((ep = strchr(fmt,')')) == NULL || ep[1] != '\0')
+ badfmt = TRUE;
+ else
+ tupsz = ep - fmt - 1;
+ }
+ else if (strlen(fmt) == 1)
+ tupsz = -1;
+ else
+ badfmt = TRUE;
+
+ if (badfmt)
+ PyErr_Format(PyExc_SystemError,"sipBuildResult(): invalid format string \"%s\"",fmt);
+ else if (tupsz < 0 || (res = PyTuple_New(tupsz)) != NULL)
+ res = buildObject(res,fmt,va);
+
+ va_end(va);
+
+ if (res == NULL && isErr != NULL)
+ *isErr = TRUE;
+
+ return res;
+}
+
+
+/*
+ * Get the values off the stack and put them into an object.
+ */
+static PyObject *buildObject(PyObject *obj, const char *fmt, va_list va)
+{
+ char ch, termch;
+ int i;
+
+ /*
+ * The format string has already been checked that it is properly formed if
+ * it is enclosed in parenthesis.
+ */
+ if (*fmt == '(')
+ {
+ termch = ')';
+ ++fmt;
+ }
+ else
+ termch = '\0';
+
+ i = 0;
+
+ while ((ch = *fmt++) != termch)
+ {
+ PyObject *el;
+
+ switch (ch)
+ {
+ case 'g':
+ {
+ char *s;
+ SIP_SSIZE_T l;
+
+ s = va_arg(va, char *);
+ l = va_arg(va, SIP_SSIZE_T);
+
+ if (s != NULL)
+ {
+ el = SIPBytes_FromStringAndSize(s, l);
+ }
+ else
+ {
+ Py_INCREF(Py_None);
+ el = Py_None;
+ }
+ }
+
+ break;
+
+ case 'G':
+#if defined(HAVE_WCHAR_H)
+ {
+ wchar_t *s;
+ SIP_SSIZE_T l;
+
+ s = va_arg(va, wchar_t *);
+ l = va_arg(va, SIP_SSIZE_T);
+
+ if (s != NULL)
+ el = PyUnicode_FromWideChar(s, l);
+ else
+ {
+ Py_INCREF(Py_None);
+ el = Py_None;
+ }
+ }
+#else
+ raiseNoWChar();
+ el = NULL;
+#endif
+
+ break;
+
+ case 'b':
+ el = PyBool_FromLong(va_arg(va,int));
+ break;
+
+ case 'c':
+ {
+ char c = va_arg(va, int);
+
+ el = SIPBytes_FromStringAndSize(&c, 1);
+ }
+
+ break;
+
+ case 'a':
+ {
+ char c = va_arg(va, int);
+
+#if PY_MAJOR_VERSION >= 3
+ el = PyUnicode_FromStringAndSize(&c, 1);
+#else
+ el = PyString_FromStringAndSize(&c, 1);
+#endif
+ }
+
+ break;
+
+ case 'w':
+#if defined(HAVE_WCHAR_H)
+ {
+ wchar_t c = va_arg(va, int);
+
+ el = PyUnicode_FromWideChar(&c, 1);
+ }
+#else
+ raiseNoWChar();
+ el = NULL;
+#endif
+
+ break;
+
+ case 'E':
+ {
+ /* This is deprecated. */
+
+ int ev = va_arg(va, int);
+ PyTypeObject *et = va_arg(va, PyTypeObject *);
+
+ el = sip_api_convert_from_enum(ev,
+ ((const sipEnumTypeObject *)et)->type);
+ }
+
+ break;
+
+ case 'F':
+ {
+ int ev = va_arg(va, int);
+ const sipTypeDef *td = va_arg(va, const sipTypeDef *);
+
+ el = sip_api_convert_from_enum(ev, td);
+ }
+
+ break;
+
+ case 'd':
+ case 'f':
+ el = PyFloat_FromDouble(va_arg(va,double));
+ break;
+
+ case 'e':
+ case 'h':
+ case 'i':
+#if PY_MAJOR_VERSION >= 3
+ el = PyLong_FromLong(va_arg(va, int));
+#else
+ el = PyInt_FromLong(va_arg(va, int));
+#endif
+ break;
+
+ case 'l':
+ el = PyLong_FromLong(va_arg(va, long));
+ break;
+
+ case 'm':
+ el = PyLong_FromUnsignedLong(va_arg(va, unsigned long));
+ break;
+
+ case 'n':
+#if defined(HAVE_LONG_LONG)
+ el = PyLong_FromLongLong(va_arg(va, PY_LONG_LONG));
+#else
+ el = PyLong_FromLong(va_arg(va, long));
+#endif
+ break;
+
+ case 'o':
+#if defined(HAVE_LONG_LONG)
+ el = PyLong_FromUnsignedLongLong(va_arg(va, unsigned PY_LONG_LONG));
+#else
+ el = PyLong_FromUnsignedLong(va_arg(va, unsigned long));
+#endif
+ break;
+
+ case 's':
+ {
+ char *s = va_arg(va, char *);
+
+ if (s != NULL)
+ {
+ el = SIPBytes_FromString(s);
+ }
+ else
+ {
+ Py_INCREF(Py_None);
+ el = Py_None;
+ }
+ }
+
+ break;
+
+ case 'A':
+ {
+ char *s = va_arg(va, char *);
+
+ if (s != NULL)
+#if PY_MAJOR_VERSION >= 3
+ el = PyUnicode_FromString(s);
+#else
+ el = PyString_FromString(s);
+#endif
+ else
+ {
+ Py_INCREF(Py_None);
+ el = Py_None;
+ }
+ }
+
+ break;
+
+ case 'x':
+#if defined(HAVE_WCHAR_H)
+ {
+ wchar_t *s = va_arg(va, wchar_t *);
+
+ if (s != NULL)
+ el = PyUnicode_FromWideChar(s, (SIP_SSIZE_T)wcslen(s));
+ else
+ {
+ Py_INCREF(Py_None);
+ el = Py_None;
+ }
+ }
+#else
+ raiseNoWChar();
+ el = NULL;
+#endif
+
+ break;
+
+ case 't':
+ case 'u':
+ el = PyLong_FromUnsignedLong(va_arg(va, unsigned));
+ break;
+
+ case 'B':
+ {
+ /* This is deprecated. */
+
+ void *p = va_arg(va,void *);
+ sipWrapperType *wt = va_arg(va, sipWrapperType *);
+ PyObject *xfer = va_arg(va, PyObject *);
+
+ el = sip_api_convert_from_new_type(p, wt->type, xfer);
+ }
+
+ break;
+
+ case 'N':
+ {
+ void *p = va_arg(va, void *);
+ const sipTypeDef *td = va_arg(va, const sipTypeDef *);
+ PyObject *xfer = va_arg(va, PyObject *);
+
+ el = sip_api_convert_from_new_type(p, td, xfer);
+ }
+
+ break;
+
+ case 'C':
+ {
+ /* This is deprecated. */
+
+ void *p = va_arg(va,void *);
+ sipWrapperType *wt = va_arg(va, sipWrapperType *);
+ PyObject *xfer = va_arg(va, PyObject *);
+
+ el = sip_api_convert_from_type(p, wt->type, xfer);
+ }
+
+ break;
+
+ case 'D':
+ {
+ void *p = va_arg(va, void *);
+ const sipTypeDef *td = va_arg(va, const sipTypeDef *);
+ PyObject *xfer = va_arg(va, PyObject *);
+
+ el = sip_api_convert_from_type(p, td, xfer);
+ }
+
+ break;
+
+ case 'r':
+ {
+ void *p = va_arg(va, void *);
+ SIP_SSIZE_T l = va_arg(va, SIP_SSIZE_T);
+ const sipTypeDef *td = va_arg(va, const sipTypeDef *);
+
+ el = convertToSequence(p, l, td);
+ }
+
+ break;
+
+ case 'R':
+ el = va_arg(va,PyObject *);
+ break;
+
+ case 'S':
+ el = va_arg(va,PyObject *);
+ Py_INCREF(el);
+ break;
+
+ case 'V':
+ el = sip_api_convert_from_void_ptr(va_arg(va, void *));
+ break;
+
+ default:
+ PyErr_Format(PyExc_SystemError,"buildObject(): invalid format character '%c'",ch);
+ el = NULL;
+ }
+
+ if (el == NULL)
+ {
+ Py_XDECREF(obj);
+ return NULL;
+ }
+
+ if (obj == NULL)
+ return el;
+
+ PyTuple_SET_ITEM(obj,i,el);
+ ++i;
+ }
+
+ return obj;
+}
+
+
+/*
+ * Parse a result object based on a format string.
+ */
+static int sip_api_parse_result(int *isErr, PyObject *method, PyObject *res,
+ const char *fmt, ...)
+{
+ int tupsz, rc = 0;
+ sipSimpleWrapper *self = NULL;
+ va_list va;
+
+ va_start(va,fmt);
+
+ /* Get self if it is provided. */
+ if (*fmt == 'S')
+ {
+ self = va_arg(va, sipSimpleWrapper *);
+ ++fmt;
+ }
+
+ /* Basic validation of the format string. */
+ if (*fmt == '(')
+ {
+ char ch;
+ const char *cp = ++fmt;
+
+ tupsz = 0;
+
+ while ((ch = *cp++) != ')')
+ {
+ if (ch == '\0')
+ {
+ PyErr_Format(PyExc_SystemError, "sipParseResult(): invalid format string \"%s\"", fmt - 1);
+ rc = -1;
+
+ break;
+ }
+
+ /*
+ * Some format characters have a sub-format so skip the character
+ * and count the sub-format character next time round.
+ */
+ if (strchr("HDC", ch) == NULL)
+ ++tupsz;
+ }
+
+ if (rc == 0)
+ if (!PyTuple_Check(res) || PyTuple_GET_SIZE(res) != tupsz)
+ {
+ sip_api_bad_catcher_result(method);
+ rc = -1;
+ }
+ }
+ else
+ tupsz = -1;
+
+ if (rc == 0)
+ {
+ char ch;
+ int i = 0;
+
+ while ((ch = *fmt++) != '\0' && ch != ')' && rc == 0)
+ {
+ PyObject *arg;
+ int invalid = FALSE;
+
+ if (tupsz > 0)
+ {
+ arg = PyTuple_GET_ITEM(res,i);
+ ++i;
+ }
+ else
+ arg = res;
+
+ switch (ch)
+ {
+ case 'g':
+ {
+ const char **p = va_arg(va, const char **);
+ SIP_SSIZE_T *szp = va_arg(va, SIP_SSIZE_T *);
+
+ if (parseBytes_AsCharArray(arg, p, szp) < 0)
+ invalid = TRUE;
+ }
+
+ break;
+
+ case 'G':
+#if defined(HAVE_WCHAR_H)
+ {
+ wchar_t **p = va_arg(va, wchar_t **);
+ SIP_SSIZE_T *szp = va_arg(va, SIP_SSIZE_T *);
+
+ if (parseWCharArray(arg, p, szp) < 0)
+ invalid = TRUE;
+ }
+#else
+ raiseNoWChar();
+ invalid = TRUE;
+#endif
+
+ break;
+
+ case 'b':
+ {
+ int v = SIPLong_AsLong(arg);
+
+ if (PyErr_Occurred())
+ invalid = TRUE;
+ else
+ sipSetBool(va_arg(va, void *), v);
+ }
+
+ break;
+
+ case 'c':
+ {
+ char *p = va_arg(va, char *);
+
+ if (parseBytes_AsChar(arg, p) < 0)
+ invalid = TRUE;
+ }
+
+ break;
+
+ case 'a':
+ {
+ char *p = va_arg(va, char *);
+ int enc;
+
+ switch (*fmt++)
+ {
+ case 'A':
+ enc = parseString_AsASCIIChar(arg, p);
+ break;
+
+ case 'L':
+ enc = parseString_AsLatin1Char(arg, p);
+ break;
+
+ case '8':
+ enc = parseString_AsUTF8Char(arg, p);
+ break;
+
+ default:
+ enc = -1;
+ }
+
+ if (enc < 0)
+ invalid = TRUE;
+ }
+
+ break;
+
+ case 'w':
+#if defined(HAVE_WCHAR_H)
+ {
+ wchar_t *p = va_arg(va, wchar_t *);
+
+ if (parseWChar(arg, p) < 0)
+ invalid = TRUE;
+ }
+#else
+ raiseNoWChar();
+ invalid = TRUE;
+#endif
+
+ break;
+
+ case 'd':
+ {
+ double v = PyFloat_AsDouble(arg);
+
+ if (PyErr_Occurred())
+ invalid = TRUE;
+ else
+ *va_arg(va,double *) = v;
+ }
+
+ break;
+
+ case 'E':
+ {
+ /* This is deprecated. */
+
+ PyTypeObject *et = va_arg(va, PyTypeObject *);
+ int *p = va_arg(va, int *);
+
+ if (sip_api_can_convert_to_enum(arg, ((sipEnumTypeObject *)et)->type))
+ *p = SIPLong_AsLong(arg);
+ else
+ invalid = TRUE;
+ }
+
+ break;
+
+ case 'F':
+ {
+ sipTypeDef *td = va_arg(va, sipTypeDef *);
+ int *p = va_arg(va, int *);
+
+ if (sip_api_can_convert_to_enum(arg, td))
+ *p = SIPLong_AsLong(arg);
+ else
+ invalid = TRUE;
+ }
+
+ break;
+
+ case 'f':
+ {
+ float v = PyFloat_AsDouble(arg);
+
+ if (PyErr_Occurred())
+ invalid = TRUE;
+ else
+ *va_arg(va,float *) = v;
+ }
+
+ break;
+
+ case 'h':
+ {
+ short v = SIPLong_AsLong(arg);
+
+ if (PyErr_Occurred())
+ invalid = TRUE;
+ else
+ *va_arg(va, short *) = v;
+ }
+
+ break;
+
+ case 't':
+ {
+ unsigned short v = sip_api_long_as_unsigned_long(arg);
+
+ if (PyErr_Occurred())
+ invalid = TRUE;
+ else
+ *va_arg(va,unsigned short *) = v;
+ }
+
+ break;
+
+ case 'e':
+ case 'i':
+ {
+ int v = SIPLong_AsLong(arg);
+
+ if (PyErr_Occurred())
+ invalid = TRUE;
+ else
+ *va_arg(va, int *) = v;
+ }
+
+ break;
+
+ case 'u':
+ {
+ unsigned v = sip_api_long_as_unsigned_long(arg);
+
+ if (PyErr_Occurred())
+ invalid = TRUE;
+ else
+ *va_arg(va,unsigned *) = v;
+ }
+
+ break;
+
+ case 'l':
+ {
+ long v = PyLong_AsLong(arg);
+
+ if (PyErr_Occurred())
+ invalid = TRUE;
+ else
+ *va_arg(va,long *) = v;
+ }
+
+ break;
+
+ case 'm':
+ {
+ unsigned long v = sip_api_long_as_unsigned_long(arg);
+
+ if (PyErr_Occurred())
+ invalid = TRUE;
+ else
+ *va_arg(va, unsigned long *) = v;
+ }
+
+ break;
+
+ case 'n':
+ {
+#if defined(HAVE_LONG_LONG)
+ PY_LONG_LONG v = PyLong_AsLongLong(arg);
+#else
+ long v = PyLong_AsLong(arg);
+#endif
+
+ if (PyErr_Occurred())
+ invalid = TRUE;
+ else
+#if defined(HAVE_LONG_LONG)
+ *va_arg(va, PY_LONG_LONG *) = v;
+#else
+ *va_arg(va, long *) = v;
+#endif
+ }
+
+ break;
+
+ case 'o':
+ {
+#if defined(HAVE_LONG_LONG)
+ unsigned PY_LONG_LONG v = PyLong_AsUnsignedLongLong(arg);
+#else
+ unsigned long v = PyLong_AsUnsignedLong(arg);
+#endif
+
+ if (PyErr_Occurred())
+ invalid = TRUE;
+ else
+#if defined(HAVE_LONG_LONG)
+ *va_arg(va, unsigned PY_LONG_LONG *) = v;
+#else
+ *va_arg(va, unsigned long *) = v;
+#endif
+ }
+
+ break;
+
+ case 's':
+ {
+ /* This is deprecated. */
+
+ const char **p = va_arg(va, const char **);
+
+ if (parseBytes_AsString(arg, p) < 0)
+ invalid = TRUE;
+ }
+
+ break;
+
+ case 'A':
+ {
+ int key = va_arg(va, int);
+ const char **p = va_arg(va, const char **);
+ PyObject *keep;
+
+ switch (*fmt++)
+ {
+ case 'A':
+ keep = parseString_AsASCIIString(arg, p);
+ break;
+
+ case 'L':
+ keep = parseString_AsLatin1String(arg, p);
+ break;
+
+ case '8':
+ keep = parseString_AsUTF8String(arg, p);
+ break;
+
+ default:
+ keep = NULL;
+ }
+
+ if (keep == NULL)
+ invalid = TRUE;
+ else
+ sip_api_keep_reference((PyObject *)self, key, keep);
+ }
+
+ break;
+
+ case 'B':
+ {
+ int key = va_arg(va, int);
+ const char **p = va_arg(va, const char **);
+
+ if (parseBytes_AsString(arg, p) < 0)
+ invalid = TRUE;
+ else
+ {
+ Py_INCREF(arg);
+ sip_api_keep_reference((PyObject *)self, key, arg);
+ }
+ }
+
+ break;
+
+ case 'x':
+#if defined(HAVE_WCHAR_H)
+ {
+ wchar_t **p = va_arg(va, wchar_t **);
+
+ if (parseWCharString(arg, p) < 0)
+ invalid = TRUE;
+ }
+#else
+ raiseNoWChar();
+ invalid = TRUE;
+#endif
+
+ break;
+
+ case 'C':
+ {
+ /* This is deprecated. */
+
+ if (*fmt == '\0')
+ invalid = TRUE;
+ else
+ {
+ int flags = *fmt++ - '0';
+ int iserr = FALSE;
+ sipWrapperType *type;
+ void **cpp;
+ int *state;
+
+ type = va_arg(va, sipWrapperType *);
+
+ if (flags & FMT_RP_NO_STATE_DEPR)
+ state = NULL;
+ else
+ state = va_arg(va, int *);
+
+ cpp = va_arg(va, void **);
+
+ *cpp = sip_api_force_convert_to_type(arg, type->type, (flags & FMT_RP_FACTORY ? arg : NULL), (flags & FMT_RP_DEREF ? SIP_NOT_NONE : 0), state, &iserr);
+
+ if (iserr)
+ invalid = TRUE;
+ }
+ }
+
+ break;
+
+ case 'D':
+ {
+ /* This is deprecated. */
+
+ if (*fmt == '\0')
+ invalid = TRUE;
+ else
+ {
+ int flags = *fmt++ - '0';
+ int iserr = FALSE;
+ const sipTypeDef *td;
+ void **cpp;
+ int *state;
+
+ td = va_arg(va, const sipTypeDef *);
+
+ if (flags & FMT_RP_NO_STATE_DEPR)
+ state = NULL;
+ else
+ state = va_arg(va, int *);
+
+ cpp = va_arg(va, void **);
+
+ *cpp = sip_api_force_convert_to_type(arg, td, (flags & FMT_RP_FACTORY ? arg : NULL), (flags & FMT_RP_DEREF ? SIP_NOT_NONE : 0), state, &iserr);
+
+ if (iserr)
+ invalid = TRUE;
+ }
+ }
+
+ break;
+
+ case 'H':
+ {
+ if (*fmt == '\0')
+ invalid = TRUE;
+ else
+ {
+ int flags = *fmt++ - '0';
+ int iserr = FALSE, state;
+ const sipTypeDef *td;
+ void *cpp, *val;
+
+ td = va_arg(va, const sipTypeDef *);
+ cpp = va_arg(va, void **);
+
+ val = sip_api_force_convert_to_type(arg, td, (flags & FMT_RP_FACTORY ? arg : NULL), (flags & FMT_RP_DEREF ? SIP_NOT_NONE : 0), &state, &iserr);
+
+ if (iserr)
+ {
+ invalid = TRUE;
+ }
+ else if (flags & FMT_RP_MAKE_COPY)
+ {
+ sipAssignFunc assign_helper;
+
+ if (sipTypeIsMapped(td))
+ assign_helper = ((const sipMappedTypeDef *)td)->mtd_assign;
+ else
+ assign_helper = ((const sipClassTypeDef *)td)->ctd_assign;
+
+ assert(assign_helper != NULL);
+
+ assign_helper(cpp, 0, val);
+ sip_api_release_type(val, td, state);
+ }
+ else
+ {
+ *(void **)cpp = val;
+ }
+ }
+ }
+
+ break;
+
+ case 'N':
+ {
+ PyTypeObject *type = va_arg(va,PyTypeObject *);
+ PyObject **p = va_arg(va,PyObject **);
+
+ if (arg == Py_None || PyObject_TypeCheck(arg,type))
+ {
+ Py_INCREF(arg);
+ *p = arg;
+ }
+ else
+ invalid = TRUE;
+ }
+
+ break;
+
+ case 'O':
+ Py_INCREF(arg);
+ *va_arg(va,PyObject **) = arg;
+ break;
+
+ case 'T':
+ {
+ PyTypeObject *type = va_arg(va,PyTypeObject *);
+ PyObject **p = va_arg(va,PyObject **);
+
+ if (PyObject_TypeCheck(arg,type))
+ {
+ Py_INCREF(arg);
+ *p = arg;
+ }
+ else
+ invalid = TRUE;
+ }
+
+ break;
+
+ case 'V':
+ {
+ void *v = sip_api_convert_to_void_ptr(arg);
+
+ if (PyErr_Occurred())
+ invalid = TRUE;
+ else
+ *va_arg(va,void **) = v;
+ }
+
+ break;
+
+ case 'Z':
+ if (arg != Py_None)
+ invalid = TRUE;
+
+ break;
+
+ default:
+ PyErr_Format(PyExc_SystemError,"sipParseResult(): invalid format character '%c'",ch);
+ rc = -1;
+ }
+
+ if (invalid)
+ {
+ sip_api_bad_catcher_result(method);
+ rc = -1;
+ break;
+ }
+ }
+ }
+
+ va_end(va);
+
+ if (isErr != NULL && rc < 0)
+ *isErr = TRUE;
+
+ return rc;
+}
+
+
+/*
+ * A thin wrapper around PyLong_AsUnsignedLong() that works around a bug in
+ * Python versions prior to v2.4 where an integer (or a named enum) causes an
+ * error.
+ */
+static unsigned long sip_api_long_as_unsigned_long(PyObject *o)
+{
+#if PY_VERSION_HEX < 0x02040000
+ if (o != NULL && !PyLong_Check(o) && PyInt_Check(o))
+ {
+ long v = PyInt_AsLong(o);
+
+ if (v < 0)
+ {
+ PyErr_SetString(PyExc_OverflowError,
+ "can't convert negative value to unsigned long");
+
+ return (unsigned long)-1;
+ }
+
+ return v;
+ }
+#endif
+
+ return PyLong_AsUnsignedLong(o);
+}
+
+
+/*
+ * Parse the arguments to a C/C++ function without any side effects.
+ */
+static int sip_api_parse_args(PyObject **parseErrp, PyObject *sipArgs,
+ const char *fmt, ...)
+{
+ int ok;
+ va_list va;
+
+ va_start(va, fmt);
+ ok = parseKwdArgs(parseErrp, sipArgs, NULL, NULL, NULL, fmt, va);
+ va_end(va);
+
+ return ok;
+}
+
+
+/*
+ * Parse the positional and/or keyword arguments to a C/C++ function without
+ * any side effects.
+ */
+static int sip_api_parse_kwd_args(PyObject **parseErrp, PyObject *sipArgs,
+ PyObject *sipKwdArgs, const char **kwdlist, PyObject **unused,
+ const char *fmt, ...)
+{
+ int ok;
+ va_list va;
+
+ /* Initialise the return of any unused keyword arguments. */
+ if (unused != NULL)
+ *unused = NULL;
+
+ va_start(va, fmt);
+ ok = parseKwdArgs(parseErrp, sipArgs, sipKwdArgs, kwdlist, unused, fmt,
+ va);
+ va_end(va);
+
+ /* Release any unused arguments if the parse failed. */
+ if (!ok && unused != NULL)
+ {
+ Py_XDECREF(*unused);
+ }
+
+ return ok;
+}
+
+
+/*
+ * Parse the arguments to a C/C++ function without any side effects.
+ */
+static int parseKwdArgs(PyObject **parseErrp, PyObject *sipArgs,
+ PyObject *sipKwdArgs, const char **kwdlist, PyObject **unused,
+ const char *fmt, va_list va_orig)
+{
+ int no_tmp_tuple, ok, selfarg;
+ sipSimpleWrapper *self;
+ PyObject *single_arg;
+ va_list va;
+
+ /* Previous second pass errors stop subsequent parses. */
+ if (*parseErrp != NULL && !PyList_Check(*parseErrp))
+ return FALSE;
+
+ /*
+ * See if we are parsing a single argument. In current versions we are
+ * told explicitly by the first character of the format string. In earlier
+ * versions we guessed (sometimes wrongly).
+ */
+ if (*fmt == '1')
+ {
+ ++fmt;
+ no_tmp_tuple = FALSE;
+ }
+ else
+ no_tmp_tuple = PyTuple_Check(sipArgs);
+
+ if (no_tmp_tuple)
+ {
+ Py_INCREF(sipArgs);
+ }
+ else if ((single_arg = PyTuple_New(1)) != NULL)
+ {
+ Py_INCREF(sipArgs);
+ PyTuple_SET_ITEM(single_arg, 0, sipArgs);
+
+ sipArgs = single_arg;
+ }
+ else
+ {
+ /* Stop all parsing and indicate an exception has been raised. */
+ Py_XDECREF(*parseErrp);
+ *parseErrp = Py_None;
+ Py_INCREF(Py_None);
+
+ return FALSE;
+ }
+
+ /*
+ * The first pass checks all the types and does conversions that are cheap
+ * and have no side effects.
+ */
+ va_copy(va, va_orig);
+ ok = parsePass1(parseErrp, &self, &selfarg, sipArgs, sipKwdArgs, kwdlist,
+ unused, fmt, va);
+ va_end(va);
+
+ if (ok)
+ {
+ /*
+ * The second pass does any remaining conversions now that we know we
+ * have the right signature.
+ */
+ va_copy(va, va_orig);
+ ok = parsePass2(self, selfarg, sipArgs, sipKwdArgs, kwdlist, fmt, va);
+ va_end(va);
+
+ /* Remove any previous failed parses. */
+ Py_XDECREF(*parseErrp);
+
+ if (ok)
+ {
+ *parseErrp = NULL;
+ }
+ else
+ {
+ /* Indicate that an exception has been raised. */
+ *parseErrp = Py_None;
+ Py_INCREF(Py_None);
+ }
+ }
+
+ Py_DECREF(sipArgs);
+
+ return ok;
+}
+
+
+/*
+ * Return a string as a Python object that describes an argument with an
+ * unexpected type.
+ */
+static PyObject *bad_type_str(int arg_nr, PyObject *arg)
+{
+#if PY_MAJOR_VERSION >= 3
+ return PyUnicode_FromFormat("argument %d has unexpected type '%s'", arg_nr,
+ Py_TYPE(arg)->tp_name);
+#else
+ return PyString_FromFormat("argument %d has unexpected type '%s'", arg_nr,
+ Py_TYPE(arg)->tp_name);
+#endif
+}
+
+
+/*
+ * Adds a failure about an argument with an incorrect type to the current list
+ * of exceptions.
+ */
+static sipErrorState sip_api_bad_callable_arg(int arg_nr, PyObject *arg)
+{
+ PyObject *detail = bad_type_str(arg_nr + 1, arg);
+
+ if (detail == NULL)
+ return sipErrorFail;
+
+ PyErr_SetObject(PyExc_TypeError, detail);
+ Py_DECREF(detail);
+
+ return sipErrorContinue;
+}
+
+
+/*
+ * Adds the current exception to the current list of exceptions (if it is a
+ * user exception) or replace the current list of exceptions.
+ */
+static void sip_api_add_exception(sipErrorState es, PyObject **parseErrp)
+{
+ assert(*parseErrp == NULL);
+
+ if (es == sipErrorContinue)
+ {
+ sipParseFailure failure;
+ PyObject *e_type, *e_traceback;
+
+ /* Get the value of the exception. */
+ PyErr_Fetch(&e_type, &failure.detail_obj, &e_traceback);
+ Py_XDECREF(e_type);
+ Py_XDECREF(e_traceback);
+
+ failure.reason = Exception;
+
+ add_failure(parseErrp, &failure);
+
+ if (failure.reason == Raised)
+ {
+ Py_XDECREF(failure.detail_obj);
+ es = sipErrorFail;
+ }
+ }
+
+ if (es == sipErrorFail)
+ {
+ Py_XDECREF(*parseErrp);
+ *parseErrp = Py_None;
+ Py_INCREF(Py_None);
+ }
+}
+
+
+/*
+ * The dtor for parse failure wrapped in a Python object.
+ */
+#if defined(SIP_USE_PYCAPSULE)
+static void failure_dtor(PyObject *capsule)
+{
+ sipParseFailure *failure = (sipParseFailure *)PyCapsule_GetPointer(capsule, NULL);
+
+ Py_XDECREF(failure->detail_obj);
+
+ sip_api_free(failure);
+}
+#else
+static void failure_dtor(void *ptr)
+{
+ sipParseFailure *failure = (sipParseFailure *)ptr;
+
+ Py_XDECREF(failure->detail_obj);
+
+ sip_api_free(failure);
+}
+#endif
+
+
+/*
+ * Add a parse failure to the current list of exceptions.
+ */
+static void add_failure(PyObject **parseErrp, sipParseFailure *failure)
+{
+ sipParseFailure *failure_copy;
+ PyObject *failure_obj;
+
+ /* Create the list if necessary. */
+ if (*parseErrp == NULL && (*parseErrp = PyList_New(0)) == NULL)
+ {
+ failure->reason = Raised;
+ return;
+ }
+
+ /*
+ * Make a copy of the failure, convert it to a Python object and add it to
+ * the list. We do it this way to make it as lightweight as possible.
+ */
+ if ((failure_copy = sip_api_malloc(sizeof (sipParseFailure))) == NULL)
+ {
+ failure->reason = Raised;
+ return;
+ }
+
+ *failure_copy = *failure;
+
+#if defined(SIP_USE_PYCAPSULE)
+ failure_obj = PyCapsule_New(failure_copy, NULL, failure_dtor);
+#else
+ failure_obj = PyCObject_FromVoidPtr(failure_copy, failure_dtor);
+#endif
+
+ if (failure_obj == NULL)
+ {
+ sip_api_free(failure_copy);
+ failure->reason = Raised;
+ return;
+ }
+
+ /* Ownership of any detail object is now with the wrapped failure. */
+ failure->detail_obj = NULL;
+
+ if (PyList_Append(*parseErrp, failure_obj) < 0)
+ {
+ Py_DECREF(failure_obj);
+ failure->reason = Raised;
+ return;
+ }
+
+ Py_DECREF(failure_obj);
+}
+
+
+/*
+ * Parse a pair of arguments to a C/C++ function without any side effects.
+ */
+static int sip_api_parse_pair(PyObject **parseErrp, PyObject *sipArg0,
+ PyObject *sipArg1, const char *fmt, ...)
+{
+ int ok, selfarg;
+ sipSimpleWrapper *self;
+ PyObject *args;
+ va_list va;
+
+ /* Previous second pass errors stop subsequent parses. */
+ if (*parseErrp != NULL && !PyList_Check(*parseErrp))
+ return FALSE;
+
+ if ((args = PyTuple_New(2)) == NULL)
+ {
+ /* Stop all parsing and indicate an exception has been raised. */
+ Py_XDECREF(*parseErrp);
+ *parseErrp = Py_None;
+ Py_INCREF(Py_None);
+
+ return FALSE;
+ }
+
+ Py_INCREF(sipArg0);
+ PyTuple_SET_ITEM(args, 0, sipArg0);
+
+ Py_INCREF(sipArg1);
+ PyTuple_SET_ITEM(args, 1, sipArg1);
+
+ /*
+ * The first pass checks all the types and does conversions that are cheap
+ * and have no side effects.
+ */
+ va_start(va, fmt);
+ ok = parsePass1(parseErrp, &self, &selfarg, args, NULL, NULL, NULL, fmt,
+ va);
+ va_end(va);
+
+ if (ok)
+ {
+ /*
+ * The second pass does any remaining conversions now that we know we
+ * have the right signature.
+ */
+ va_start(va, fmt);
+ ok = parsePass2(self, selfarg, args, NULL, NULL, fmt, va);
+ va_end(va);
+
+ /* Remove any previous failed parses. */
+ Py_XDECREF(*parseErrp);
+
+ if (ok)
+ {
+ *parseErrp = NULL;
+ }
+ else
+ {
+ /* Indicate that an exception has been raised. */
+ *parseErrp = Py_None;
+ Py_INCREF(Py_None);
+ }
+ }
+
+ Py_DECREF(args);
+
+ return ok;
+}
+
+
+/*
+ * First pass of the argument parse, converting those that can be done so
+ * without any side effects. Return TRUE if the arguments matched.
+ */
+static int parsePass1(PyObject **parseErrp, sipSimpleWrapper **selfp,
+ int *selfargp, PyObject *sipArgs, PyObject *sipKwdArgs,
+ const char **kwdlist, PyObject **unused, const char *fmt, va_list va)
+{
+ int compulsory, argnr, nr_args;
+ SIP_SSIZE_T nr_pos_args, nr_kwd_args, nr_kwd_args_used;
+ sipParseFailure failure;
+
+ failure.reason = Ok;
+ failure.detail_obj = NULL;
+ compulsory = TRUE;
+ argnr = 0;
+ nr_args = 0;
+ nr_pos_args = PyTuple_GET_SIZE(sipArgs);
+ nr_kwd_args = nr_kwd_args_used = 0;
+
+ if (sipKwdArgs != NULL)
+ {
+ assert(PyDict_Check(sipKwdArgs));
+
+ nr_kwd_args = PyDict_Size(sipKwdArgs);
+ }
+
+ /*
+ * Handle those format characters that deal with the "self" argument. They
+ * will always be the first one.
+ */
+ *selfp = NULL;
+ *selfargp = FALSE;
+
+ switch (*fmt++)
+ {
+ case 'B':
+ case 'p':
+ {
+ PyObject *self;
+ sipTypeDef *td;
+
+ self = *va_arg(va, PyObject **);
+ td = va_arg(va, sipTypeDef *);
+ va_arg(va, void **);
+
+ if (self == NULL)
+ {
+ if (!getSelfFromArgs(td, sipArgs, argnr, selfp))
+ {
+ failure.reason = Unbound;
+ failure.detail_str = sipPyNameOfContainer(
+ &((sipClassTypeDef *)td)->ctd_container, td);
+ break;
+ }
+
+ *selfargp = TRUE;
+ ++argnr;
+ }
+ else
+ *selfp = (sipSimpleWrapper *)self;
+
+ break;
+ }
+
+ case 'C':
+ *selfp = (sipSimpleWrapper *)va_arg(va,PyObject *);
+ break;
+
+ default:
+ --fmt;
+ }
+
+ /* Now handle the remaining arguments. */
+ while (failure.reason == Ok)
+ {
+ char ch;
+ PyObject *arg;
+
+ PyErr_Clear();
+
+ /* See if the following arguments are optional. */
+ if ((ch = *fmt++) == '|')
+ {
+ compulsory = FALSE;
+ ch = *fmt++;
+ }
+
+ /* See if we don't expect anything else. */
+
+ if (ch == '\0')
+ {
+ if (argnr < nr_pos_args)
+ {
+ /* There are still positional arguments. */
+ failure.reason = TooMany;
+ }
+ else if (nr_kwd_args_used != nr_kwd_args)
+ {
+ /*
+ * Take a shortcut if no keyword arguments were used and we are
+ * interested in them.
+ */
+ if (nr_kwd_args_used == 0 && unused != NULL)
+ {
+ Py_INCREF(sipKwdArgs);
+ *unused = sipKwdArgs;
+ }
+ else
+ {
+ PyObject *key, *value, *unused_dict = NULL;
+ SIP_SSIZE_T pos = 0;
+
+ /*
+ * Go through the keyword arguments to find any that were
+ * duplicates of positional arguments. For the remaining
+ * ones remember the unused ones if we are interested.
+ */
+ while (PyDict_Next(sipKwdArgs, &pos, &key, &value))
+ {
+ int a;
+
+#if PY_MAJOR_VERSION >= 3
+ if (!PyUnicode_Check(key))
+#else
+ if (!PyString_Check(key))
+#endif
+ {
+ failure.reason = KeywordNotString;
+ failure.detail_obj = key;
+ Py_INCREF(key);
+ break;
+ }
+
+ if (kwdlist != NULL)
+ {
+ /* Get the argument's index if it is one. */
+ for (a = 0; a < nr_args; ++a)
+ {
+ const char *name = kwdlist[a];
+
+ if (name == NULL)
+ continue;
+
+#if PY_MAJOR_VERSION >= 3
+ if (PyUnicode_CompareWithASCIIString(key, name) == 0)
+#else
+ if (strcmp(PyString_AS_STRING(key), name) == 0)
+#endif
+ break;
+ }
+ }
+ else
+ {
+ a = nr_args;
+ }
+
+ if (a == nr_args)
+ {
+ /*
+ * The name doesn't correspond to a keyword
+ * argument.
+ */
+ if (unused == NULL)
+ {
+ /*
+ * It may correspond to a keyword argument of a
+ * different overload.
+ */
+ failure.reason = UnknownKeyword;
+ failure.detail_obj = key;
+ Py_INCREF(key);
+
+ break;
+ }
+
+ /*
+ * Add it to the dictionary of unused arguments
+ * creating it if necessary. Note that if the
+ * unused arguments are actually used by a later
+ * overload then the parse will incorrectly
+ * succeed. This should be picked up (perhaps with
+ * a misleading exception) so long as the code that
+ * handles the unused arguments checks that it can
+ * handle them all.
+ */
+ if (unused_dict == NULL && (*unused = unused_dict = PyDict_New()) == NULL)
+ {
+ failure.reason = Raised;
+ break;
+ }
+
+ if (PyDict_SetItem(unused_dict, key, value) < 0)
+ {
+ failure.reason = Raised;
+ break;
+ }
+ }
+ else if (a < nr_pos_args)
+ {
+ /*
+ * The argument has been given positionally and as
+ * a keyword.
+ */
+ failure.reason = Duplicate;
+ failure.detail_obj = key;
+ Py_INCREF(key);
+ break;
+ }
+ }
+ }
+ }
+
+ break;
+ }
+
+ /* Get the next argument. */
+ arg = NULL;
+ failure.arg_nr = -1;
+ failure.arg_name = NULL;
+
+ if (argnr < nr_pos_args)
+ {
+ arg = PyTuple_GET_ITEM(sipArgs, argnr);
+ failure.arg_nr = argnr + 1;
+ }
+ else if (sipKwdArgs != NULL && kwdlist != NULL)
+ {
+ const char *name = kwdlist[argnr];
+
+ if (name != NULL)
+ {
+ arg = PyDict_GetItemString(sipKwdArgs, name);
+
+ if (arg != NULL)
+ ++nr_kwd_args_used;
+
+ failure.arg_name = name;
+ }
+ }
+
+ ++argnr;
+ ++nr_args;
+
+ if (arg == NULL && compulsory)
+ {
+ if (ch == 'W')
+ {
+ /*
+ * A variable number of arguments was allowed but none were
+ * given.
+ */
+ break;
+ }
+
+ /* An argument was required. */
+ failure.reason = TooFew;
+
+ /*
+ * Check if there were any unused keyword arguments so that we give
+ * a (possibly) more accurate diagnostic in the case that a keyword
+ * argument has been mis-spelled.
+ */
+ if (unused == NULL && sipKwdArgs != NULL && nr_kwd_args_used != nr_kwd_args)
+ {
+ PyObject *key, *value;
+ SIP_SSIZE_T pos = 0;
+
+ while (PyDict_Next(sipKwdArgs, &pos, &key, &value))
+ {
+ int a;
+
+#if PY_MAJOR_VERSION >= 3
+ if (!PyUnicode_Check(key))
+#else
+ if (!PyString_Check(key))
+#endif
+ {
+ failure.reason = KeywordNotString;
+ failure.detail_obj = key;
+ Py_INCREF(key);
+ break;
+ }
+
+ if (kwdlist != NULL)
+ {
+ /* Get the argument's index if it is one. */
+ for (a = 0; a < nr_args; ++a)
+ {
+ const char *name = kwdlist[a];
+
+ if (name == NULL)
+ continue;
+
+#if PY_MAJOR_VERSION >= 3
+ if (PyUnicode_CompareWithASCIIString(key, name) == 0)
+#else
+ if (strcmp(PyString_AS_STRING(key), name) == 0)
+#endif
+ break;
+ }
+ }
+ else
+ {
+ a = nr_args;
+ }
+
+ if (a == nr_args)
+ {
+ failure.reason = UnknownKeyword;
+ failure.detail_obj = key;
+ Py_INCREF(key);
+
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+
+ /*
+ * Handle the format character even if we don't have an argument so
+ * that we skip the right number of arguments.
+ */
+ switch (ch)
+ {
+ case 'W':
+ /* Ellipsis. */
+ break;
+
+ case '@':
+ {
+ /* Implement /GetWrapper/. */
+
+ PyObject **p = va_arg(va, PyObject **);
+
+ if (arg != NULL)
+ *p = arg;
+
+ /* Process the same argument next time round. */
+ --argnr;
+ --nr_args;
+
+ break;
+ }
+
+ case 's':
+ {
+ /* String from a Python bytes or None. */
+
+ const char **p = va_arg(va, const char **);
+
+ if (arg != NULL && parseBytes_AsString(arg, p) < 0)
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+
+ break;
+ }
+
+ case 'A':
+ {
+ /* String from a Python string or None. */
+
+ PyObject **keep = va_arg(va, PyObject **);
+ const char **p = va_arg(va, const char **);
+ char sub_fmt = *fmt++;
+
+ if (arg != NULL)
+ {
+ PyObject *s;
+
+ switch (sub_fmt)
+ {
+ case 'A':
+ s = parseString_AsASCIIString(arg, p);
+ break;
+
+ case 'L':
+ s = parseString_AsLatin1String(arg, p);
+ break;
+
+ case '8':
+ s = parseString_AsUTF8String(arg, p);
+ break;
+ }
+
+ if (s == NULL)
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ else
+ {
+ *keep = s;
+ }
+ }
+
+ break;
+ }
+
+ case 'x':
+#if defined(HAVE_WCHAR_H)
+ {
+ /* Wide string or None. */
+
+ wchar_t **p = va_arg(va, wchar_t **);
+
+ if (arg != NULL && parseWCharString(arg, p) < 0)
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+
+ break;
+ }
+#else
+ raiseNoWChar();
+ failure.reason = Raised;
+ break;
+#endif
+
+ case 'U':
+ {
+ /* Slot name or callable, return the name or callable. */
+
+ char **sname = va_arg(va, char **);
+ PyObject **scall = va_arg(va, PyObject **);
+
+ if (arg != NULL)
+ {
+ *sname = NULL;
+ *scall = NULL;
+
+ if (SIPBytes_Check(arg))
+ {
+ char *s = SIPBytes_AS_STRING(arg);
+
+ if (*s == '1' || *s == '2' || *s == '9')
+ {
+ *sname = s;
+ }
+ else
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ }
+ else if (PyCallable_Check(arg))
+ {
+ *scall = arg;
+ }
+ else if (arg != Py_None)
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ }
+
+ break;
+ }
+
+ case 'S':
+ {
+ /* Slot name, return the name. */
+
+ char **p = va_arg(va, char **);
+
+ if (arg != NULL)
+ {
+ if (SIPBytes_Check(arg))
+ {
+ char *s = SIPBytes_AS_STRING(arg);
+
+ if (*s == '1' || *s == '2' || *s == '9')
+ {
+ *p = s;
+ }
+ else
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ }
+ else
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ }
+
+ break;
+ }
+
+ case 'G':
+ {
+ /* Signal name, return the name. */
+
+ char **p = va_arg(va, char **);
+
+ if (arg != NULL)
+ {
+ if (SIPBytes_Check(arg))
+ {
+ char *s = SIPBytes_AS_STRING(arg);
+
+ if (*s == '2' || *s == '9')
+ {
+ *p = s;
+ }
+ else
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ }
+ else
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ }
+
+ break;
+ }
+
+ case 'r':
+ {
+ /* Sequence of class or mapped type instances. */
+
+ const sipTypeDef *td;
+
+ td = va_arg(va, const sipTypeDef *);
+ va_arg(va, void **);
+ va_arg(va, SIP_SSIZE_T *);
+
+ if (arg != NULL && !canConvertFromSequence(arg, td))
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+
+ break;
+ }
+
+ case 'J':
+ {
+ /* Class or mapped type instance. */
+
+ char sub_fmt = *fmt++;
+ const sipTypeDef *td;
+ int flags = sub_fmt - '0';
+ int iflgs = 0;
+
+ td = va_arg(va, const sipTypeDef *);
+ va_arg(va, void **);
+
+ if (flags & FMT_AP_DEREF)
+ iflgs |= SIP_NOT_NONE;
+
+ if (flags & FMT_AP_TRANSFER_THIS)
+ va_arg(va, PyObject **);
+
+ if (flags & FMT_AP_NO_CONVERTORS)
+ iflgs |= SIP_NO_CONVERTORS;
+ else
+ va_arg(va, int *);
+
+ if (arg != NULL && !sip_api_can_convert_to_type(arg, td, iflgs))
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+
+ break;
+ }
+
+ case 'N':
+ {
+ /* Python object of given type or None. */
+
+ PyTypeObject *type = va_arg(va,PyTypeObject *);
+ PyObject **p = va_arg(va,PyObject **);
+
+ if (arg != NULL)
+ {
+ if (arg == Py_None || PyObject_TypeCheck(arg,type))
+ {
+ *p = arg;
+ }
+ else
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ }
+
+ break;
+ }
+
+ case 'P':
+ {
+ /* Python object of any type with a sub-format. */
+
+ va_arg(va, PyObject **);
+
+ /* Skip the sub-format. */
+ ++fmt;
+
+ break;
+ }
+
+ case 'T':
+ {
+ /* Python object of given type. */
+
+ PyTypeObject *type = va_arg(va, PyTypeObject *);
+ PyObject **p = va_arg(va, PyObject **);
+
+ if (arg != NULL)
+ {
+ if (PyObject_TypeCheck(arg,type))
+ {
+ *p = arg;
+ }
+ else
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ }
+
+ break;
+ }
+
+ case 'R':
+ {
+ /* Sub-class of QObject. */
+
+ PyObject **p = va_arg(va, PyObject **);
+
+ if (arg != NULL)
+ {
+ if (isQObject(arg))
+ {
+ *p = arg;
+ }
+ else
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ }
+
+ break;
+ }
+
+ case 'F':
+ {
+ /* Python callable object. */
+
+ PyObject **p = va_arg(va, PyObject **);
+
+ if (arg != NULL)
+ {
+ if (PyCallable_Check(arg))
+ {
+ *p = arg;
+ }
+ else
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ }
+
+ break;
+ }
+
+ case 'H':
+ {
+ /* Python callable object or None. */
+
+ PyObject **p = va_arg(va, PyObject **);
+
+ if (arg != NULL)
+ {
+ if (arg == Py_None || PyCallable_Check(arg))
+ {
+ *p = arg;
+ }
+ else
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ }
+
+ break;
+ }
+
+ case 'q':
+ {
+ /* Qt receiver to connect. */
+
+ va_arg(va, char *);
+ va_arg(va, void **);
+ va_arg(va, const char **);
+
+ if (arg != NULL && !isQObject(arg))
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+
+ break;
+ }
+
+ case 'Q':
+ {
+ /* Qt receiver to disconnect. */
+
+ va_arg(va, char *);
+ va_arg(va, void **);
+ va_arg(va, const char **);
+
+ if (arg != NULL && !isQObject(arg))
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+
+ break;
+ }
+
+ case 'g':
+ case 'y':
+ {
+ /* Python slot to connect. */
+
+ va_arg(va, char *);
+ va_arg(va, void **);
+ va_arg(va, const char **);
+
+ if (arg != NULL && (sipQtSupport == NULL || !PyCallable_Check(arg)))
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+
+ break;
+ }
+
+ case 'Y':
+ {
+ /* Python slot to disconnect. */
+
+ va_arg(va, char *);
+ va_arg(va, void **);
+ va_arg(va, const char **);
+
+ if (arg != NULL && (sipQtSupport == NULL || !PyCallable_Check(arg)))
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+
+ break;
+ }
+
+ case 'k':
+ {
+ /* Char array or None. */
+
+ const char **p = va_arg(va, const char **);
+ SIP_SSIZE_T *szp = va_arg(va, SIP_SSIZE_T *);
+
+ if (arg != NULL && parseBytes_AsCharArray(arg, p, szp) < 0)
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+
+ break;
+ }
+
+ case 'K':
+#if defined(HAVE_WCHAR_H)
+ {
+ /* Wide char array or None. */
+
+ wchar_t **p = va_arg(va, wchar_t **);
+ SIP_SSIZE_T *szp = va_arg(va, SIP_SSIZE_T *);
+
+ if (arg != NULL && parseWCharArray(arg, p, szp) < 0)
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+
+ break;
+ }
+#else
+ raiseNoWChar();
+ failure.reason = Raised;
+ break
+#endif
+
+ case 'c':
+ {
+ /* Character from a Python bytes. */
+
+ char *p = va_arg(va, char *);
+
+ if (arg != NULL && parseBytes_AsChar(arg, p) < 0)
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+
+ break;
+ }
+
+ case 'a':
+ {
+ /* Character from a Python string. */
+
+ char *p = va_arg(va, char *);
+ char sub_fmt = *fmt++;
+
+ if (arg != NULL)
+ {
+ int enc;
+
+ switch (sub_fmt)
+ {
+ case 'A':
+ enc = parseString_AsASCIIChar(arg, p);
+ break;
+
+ case 'L':
+ enc = parseString_AsLatin1Char(arg, p);
+ break;
+
+ case '8':
+ enc = parseString_AsUTF8Char(arg, p);
+ break;
+ }
+
+ if (enc < 0)
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ }
+
+ break;
+ }
+
+ case 'w':
+#if defined(HAVE_WCHAR_H)
+ {
+ /* Wide character. */
+
+ wchar_t *p = va_arg(va, wchar_t *);
+
+ if (arg != NULL && parseWChar(arg, p) < 0)
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+
+ break;
+ }
+#else
+ raiseNoWChar();
+ failure.reason = Raised;
+ break
+#endif
+
+ case 'b':
+ {
+ /* Bool. */
+
+ void *p = va_arg(va, void *);
+
+ if (arg != NULL)
+ {
+ int v = SIPLong_AsLong(arg);
+
+ if (PyErr_Occurred())
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ else
+ {
+ sipSetBool(p, v);
+ }
+ }
+
+ break;
+ }
+
+ case 'E':
+ {
+ /* Named enum or integer. */
+
+ sipTypeDef *td = va_arg(va, sipTypeDef *);
+
+ va_arg(va, int *);
+
+ if (arg != NULL && !sip_api_can_convert_to_enum(arg, td))
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ }
+
+ break;
+
+ case 'e':
+ case 'i':
+ {
+ /* Integer or anonymous enum. */
+
+ int *p = va_arg(va, int *);
+
+ if (arg != NULL)
+ {
+ int v = SIPLong_AsLong(arg);
+
+ if (PyErr_Occurred())
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ else
+ {
+ *p = v;
+ }
+ }
+
+ break;
+ }
+
+ case 'u':
+ {
+ /* Unsigned integer. */
+
+ unsigned *p = va_arg(va, unsigned *);
+
+ if (arg != NULL)
+ {
+ unsigned v = sip_api_long_as_unsigned_long(arg);
+
+ if (PyErr_Occurred())
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ else
+ {
+ *p = v;
+ }
+ }
+
+ break;
+ }
+
+ case 'h':
+ {
+ /* Short integer. */
+
+ short *p = va_arg(va, short *);
+
+ if (arg != NULL)
+ {
+ short v = SIPLong_AsLong(arg);
+
+ if (PyErr_Occurred())
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ else
+ {
+ *p = v;
+ }
+ }
+
+ break;
+ }
+
+ case 't':
+ {
+ /* Unsigned short integer. */
+
+ unsigned short *p = va_arg(va, unsigned short *);
+
+ if (arg != NULL)
+ {
+ unsigned short v = sip_api_long_as_unsigned_long(arg);
+
+ if (PyErr_Occurred())
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ else
+ {
+ *p = v;
+ }
+ }
+
+ break;
+ }
+
+ case 'l':
+ {
+ /* Long integer. */
+
+ long *p = va_arg(va, long *);
+
+ if (arg != NULL)
+ {
+ long v = PyLong_AsLong(arg);
+
+ if (PyErr_Occurred())
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ else
+ {
+ *p = v;
+ }
+ }
+
+ break;
+ }
+
+ case 'm':
+ {
+ /* Unsigned long integer. */
+
+ unsigned long *p = va_arg(va, unsigned long *);
+
+ if (arg != NULL)
+ {
+ unsigned long v = sip_api_long_as_unsigned_long(arg);
+
+ if (PyErr_Occurred())
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ else
+ {
+ *p = v;
+ }
+ }
+
+ break;
+ }
+
+ case 'n':
+ {
+ /* Long long integer. */
+
+#if defined(HAVE_LONG_LONG)
+ PY_LONG_LONG *p = va_arg(va, PY_LONG_LONG *);
+#else
+ long *p = va_arg(va, long *);
+#endif
+
+ if (arg != NULL)
+ {
+#if defined(HAVE_LONG_LONG)
+ PY_LONG_LONG v = PyLong_AsLongLong(arg);
+#else
+ long v = PyLong_AsLong(arg);
+#endif
+
+ if (PyErr_Occurred())
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ else
+ {
+ *p = v;
+ }
+ }
+
+ break;
+ }
+
+ case 'o':
+ {
+ /* Unsigned long long integer. */
+
+#if defined(HAVE_LONG_LONG)
+ unsigned PY_LONG_LONG *p = va_arg(va, unsigned PY_LONG_LONG *);
+#else
+ unsigned long *p = va_arg(va, unsigned long *);
+#endif
+
+ if (arg != NULL)
+ {
+#if defined(HAVE_LONG_LONG)
+ unsigned PY_LONG_LONG v = PyLong_AsUnsignedLongLong(arg);
+#else
+ unsigned long v = PyLong_AsUnsignedLong(arg);
+#endif
+
+ if (PyErr_Occurred())
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ else
+ {
+ *p = v;
+ }
+ }
+
+ break;
+ }
+
+ case 'f':
+ {
+ /* Float. */
+
+ float *p = va_arg(va, float *);
+
+ if (arg != NULL)
+ {
+ double v = PyFloat_AsDouble(arg);
+
+ if (PyErr_Occurred())
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ else
+ {
+ *p = (float)v;
+ }
+ }
+
+ break;
+ }
+
+ case 'X':
+ {
+ /* Constrained types. */
+
+ char sub_fmt = *fmt++;
+
+ if (sub_fmt == 'E')
+ {
+ /* Named enum. */
+
+ sipTypeDef *td = va_arg(va, sipTypeDef *);
+
+ va_arg(va, int *);
+
+ if (arg != NULL && !PyObject_TypeCheck(arg, sipTypeAsPyTypeObject(td)))
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ }
+ else
+ {
+ void *p = va_arg(va, void *);
+
+ if (arg != NULL)
+ {
+ switch (sub_fmt)
+ {
+ case 'b':
+ {
+ /* Boolean. */
+
+ if (PyBool_Check(arg))
+ {
+ sipSetBool(p, (arg == Py_True));
+ }
+ else
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+
+ break;
+ }
+
+ case 'd':
+ {
+ /* Double float. */
+
+ if (PyFloat_Check(arg))
+ {
+ *(double *)p = PyFloat_AS_DOUBLE(arg);
+ }
+ else
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+
+ break;
+ }
+
+ case 'f':
+ {
+ /* Float. */
+
+ if (PyFloat_Check(arg))
+ {
+ *(float *)p = (float)PyFloat_AS_DOUBLE(arg);
+ }
+ else
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+
+ break;
+ }
+
+ case 'i':
+ {
+ /* Integer. */
+
+#if PY_MAJOR_VERSION >= 3
+ if (PyLong_Check(arg))
+ {
+ *(int *)p = PyLong_AS_LONG(arg);
+ }
+#else
+ if (PyInt_Check(arg))
+ {
+ *(int *)p = PyInt_AS_LONG(arg);
+ }
+#endif
+ else
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ break;
+ }
+
+ case 'd':
+ {
+ /* Double float. */
+
+ double *p = va_arg(va,double *);
+
+ if (arg != NULL)
+ {
+ double v = PyFloat_AsDouble(arg);
+
+ if (PyErr_Occurred())
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ else
+ {
+ *p = v;
+ }
+ }
+
+ break;
+ }
+
+ case 'v':
+ {
+ /* Void pointer. */
+
+ void **p = va_arg(va, void **);
+
+ if (arg != NULL)
+ {
+ void *v = sip_api_convert_to_void_ptr(arg);
+
+ if (PyErr_Occurred())
+ {
+ failure.reason = WrongType;
+ failure.detail_obj = arg;
+ Py_INCREF(arg);
+ }
+ else
+ {
+ *p = v;
+ }
+ }
+
+ break;
+ }
+ }
+
+ if (failure.reason == Ok && ch == 'W')
+ {
+ /* An ellipsis matches everything and ends the parse. */
+ break;
+ }
+ }
+
+ /* Handle parse failures appropriately. */
+
+ if (failure.reason == Ok)
+ return TRUE;
+
+ if (failure.reason != Raised)
+ {
+ add_failure(parseErrp, &failure);
+ }
+
+ if (failure.reason == Raised)
+ {
+ Py_XDECREF(failure.detail_obj);
+
+ /*
+ * The error isn't a user error so don't bother with the detail of the
+ * overload.
+ */
+ Py_XDECREF(*parseErrp);
+ *parseErrp = Py_None;
+ Py_INCREF(Py_None);
+ }
+
+ return FALSE;
+}
+
+
+/*
+ * Second pass of the argument parse, converting the remaining ones that might
+ * have side effects. Return TRUE if there was no error.
+ */
+static int parsePass2(sipSimpleWrapper *self, int selfarg, PyObject *sipArgs,
+ PyObject *sipKwdArgs, const char **kwdlist, const char *fmt,
+ va_list va)
+{
+ int a, ok;
+ SIP_SSIZE_T nr_pos_args;
+
+ /* Handle the converions of "self" first. */
+ switch (*fmt++)
+ {
+ case 'B':
+ {
+ /*
+ * The address of a C++ instance when calling one of its public
+ * methods.
+ */
+
+ const sipTypeDef *td;
+ void **p;
+
+ *va_arg(va, PyObject **) = (PyObject *)self;
+ td = va_arg(va, const sipTypeDef *);
+ p = va_arg(va, void **);
+
+ if ((*p = sip_api_get_cpp_ptr(self, td)) == NULL)
+ return FALSE;
+
+ break;
+ }
+
+ case 'p':
+ {
+ /*
+ * The address of a C++ instance when calling one of its protected
+ * methods.
+ */
+
+ const sipTypeDef *td;
+ void **p;
+
+ *va_arg(va, PyObject **) = (PyObject *)self;
+ td = va_arg(va, const sipTypeDef *);
+ p = va_arg(va, void **);
+
+ if ((*p = getComplexCppPtr(self, td)) == NULL)
+ return FALSE;
+
+ break;
+ }
+
+ case 'C':
+ va_arg(va, PyObject *);
+ break;
+
+ default:
+ --fmt;
+ }
+
+ ok = TRUE;
+ nr_pos_args = PyTuple_GET_SIZE(sipArgs);
+
+ for (a = (selfarg ? 1 : 0); *fmt != '\0' && *fmt != 'W' && ok; ++a)
+ {
+ char ch;
+ PyObject *arg;
+
+ /* Skip the optional character. */
+ if ((ch = *fmt++) == '|')
+ ch = *fmt++;
+
+ /* Get the next argument. */
+ arg = NULL;
+
+ if (a < nr_pos_args)
+ {
+ arg = PyTuple_GET_ITEM(sipArgs, a);
+ }
+ else if (sipKwdArgs != NULL)
+ {
+ const char *name = kwdlist[a];
+
+ if (name != NULL)
+ arg = PyDict_GetItemString(sipKwdArgs, name);
+ }
+
+ /*
+ * Do the outstanding conversions. For most types it has already been
+ * done, so we are just skipping the parameters.
+ */
+ switch (ch)
+ {
+ case '@':
+ /* Implement /GetWrapper/. */
+ va_arg(va, PyObject **);
+
+ /* Process the same argument next time round. */
+ --a;
+
+ break;
+
+ case 'q':
+ {
+ /* Qt receiver to connect. */
+
+ char *sig = va_arg(va, char *);
+ void **rx = va_arg(va, void **);
+ const char **slot = va_arg(va, const char **);
+
+ if (arg != NULL)
+ {
+ *rx = sip_api_convert_rx((sipWrapper *)self, sig, arg,
+ *slot, slot, 0);
+
+ if (*rx == NULL)
+ return FALSE;
+ }
+
+ break;
+ }
+
+ case 'Q':
+ {
+ /* Qt receiver to disconnect. */
+
+ char *sig = va_arg(va, char *);
+ void **rx = va_arg(va, void **);
+ const char **slot = va_arg(va, const char **);
+
+ if (arg != NULL)
+ *rx = sipGetRx(self, sig, arg, *slot, slot);
+
+ break;
+ }
+
+ case 'g':
+ {
+ /* Python single shot slot to connect. */
+
+ char *sig = va_arg(va, char *);
+ void **rx = va_arg(va, void **);
+ const char **slot = va_arg(va, const char **);
+
+ if (arg != NULL)
+ {
+ *rx = sip_api_convert_rx((sipWrapper *)self, sig, arg,
+ NULL, slot, SIP_SINGLE_SHOT);
+
+ if (*rx == NULL)
+ return FALSE;
+ }
+
+ break;
+ }
+
+ case 'y':
+ {
+ /* Python slot to connect. */
+
+ char *sig = va_arg(va, char *);
+ void **rx = va_arg(va, void **);
+ const char **slot = va_arg(va, const char **);
+
+ if (arg != NULL)
+ {
+ *rx = sip_api_convert_rx((sipWrapper *)self, sig, arg,
+ NULL, slot, 0);
+
+ if (*rx == NULL)
+ return FALSE;
+ }
+
+ break;
+ }
+
+ case 'Y':
+ {
+ /* Python slot to disconnect. */
+
+ char *sig = va_arg(va, char *);
+ void **rx = va_arg(va, void **);
+ const char **slot = va_arg(va, const char **);
+
+ if (arg != NULL)
+ *rx = sipGetRx(self, sig, arg, NULL, slot);
+
+ break;
+ }
+
+ case 'r':
+ {
+ /* Sequence of class or mapped type instances. */
+
+ const sipTypeDef *td;
+ void **array;
+ SIP_SSIZE_T *nr_elem;
+
+ td = va_arg(va, const sipTypeDef *);
+ array = va_arg(va, void **);
+ nr_elem = va_arg(va, SIP_SSIZE_T *);
+
+ if (arg != NULL && !convertFromSequence(arg, td, array, nr_elem))
+ return FALSE;
+
+ break;
+ }
+
+ case 'J':
+ {
+ /* Class or mapped type instance. */
+
+ int flags = *fmt++ - '0';
+ const sipTypeDef *td;
+ void **p;
+ int iflgs = 0;
+ int *state;
+ PyObject *xfer, **owner;
+
+ td = va_arg(va, const sipTypeDef *);
+ p = va_arg(va, void **);
+
+ if (flags & FMT_AP_TRANSFER)
+ xfer = (self ? (PyObject *)self : arg);
+ else if (flags & FMT_AP_TRANSFER_BACK)
+ xfer = Py_None;
+ else
+ xfer = NULL;
+
+ if (flags & FMT_AP_DEREF)
+ iflgs |= SIP_NOT_NONE;
+
+ if (flags & FMT_AP_TRANSFER_THIS)
+ owner = va_arg(va, PyObject **);
+
+ if (flags & FMT_AP_NO_CONVERTORS)
+ {
+ iflgs |= SIP_NO_CONVERTORS;
+ state = NULL;
+ }
+ else
+ {
+ state = va_arg(va, int *);
+ }
+
+ if (arg != NULL)
+ {
+ int iserr = FALSE;
+
+ *p = sip_api_convert_to_type(arg, td, xfer, iflgs, state,
+ &iserr);
+
+ if (iserr)
+ return FALSE;
+
+ if (flags & FMT_AP_TRANSFER_THIS && *p != NULL)
+ *owner = arg;
+ }
+
+ break;
+ }
+
+ case 'P':
+ {
+ /* Python object of any type with a sub-format. */
+
+ PyObject **p = va_arg(va, PyObject **);
+ int flags = *fmt++ - '0';
+
+ if (arg != NULL)
+ {
+ if (flags & FMT_AP_TRANSFER)
+ {
+ Py_XINCREF(arg);
+ }
+ else if (flags & FMT_AP_TRANSFER_BACK)
+ {
+ Py_XDECREF(arg);
+ }
+
+ *p = arg;
+ }
+
+ break;
+ }
+
+ case 'X':
+ {
+ /* Constrained types. */
+
+ va_arg(va, void *);
+
+ if (*fmt++ == 'E')
+ {
+ /* Named enum. */
+
+ int *p = va_arg(va, int *);
+
+ if (arg != NULL)
+ *p = SIPLong_AsLong(arg);
+ }
+
+ break;
+ }
+
+ case 'E':
+ {
+ /* Named enum. */
+
+ int *p;
+
+ va_arg(va, sipTypeDef *);
+ p = va_arg(va, int *);
+
+ if (arg != NULL)
+ *p = SIPLong_AsLong(arg);
+
+ break;
+ }
+
+ /*
+ * These need special handling because they have a sub-format
+ * character.
+ */
+ case 'A':
+ va_arg(va, void *);
+
+ /* Drop through. */
+
+ case 'a':
+ va_arg(va, void *);
+ fmt++;
+ break;
+
+ /*
+ * Every other argument is a pointer and only differ in how many there
+ * are.
+ */
+ case 'N':
+ case 'T':
+ case 'k':
+ case 'K':
+ va_arg(va, void *);
+
+ /* Drop through. */
+
+ default:
+ va_arg(va, void *);
+ }
+ }
+
+ /* Handle any ellipsis argument. */
+ if (*fmt == 'W')
+ {
+ PyObject *al;
+ int da = 0;
+
+ /* Create a tuple for any remaining arguments. */
+ if ((al = PyTuple_New(nr_pos_args - a)) == NULL)
+ return FALSE;
+
+ while (a < nr_pos_args)
+ {
+ PyObject *arg = PyTuple_GET_ITEM(sipArgs, a);
+
+ /* Add the remaining argument to the tuple. */
+ Py_INCREF(arg);
+ PyTuple_SET_ITEM(al, da, arg);
+
+ ++a;
+ ++da;
+ }
+
+ /* Return the tuple. */
+ *va_arg(va, PyObject **) = al;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Return TRUE if an object is a QObject.
+ */
+static int isQObject(PyObject *obj)
+{
+ return (sipQtSupport != NULL && PyObject_TypeCheck(obj, sipTypeAsPyTypeObject(sipQObjectType)));
+}
+
+
+/*
+ * See if a Python object is a sequence of a particular type.
+ */
+static int canConvertFromSequence(PyObject *seq, const sipTypeDef *td)
+{
+ SIP_SSIZE_T i, size = PySequence_Size(seq);
+
+ if (size < 0)
+ return FALSE;
+
+ for (i = 0; i < size; ++i)
+ {
+ int ok;
+ PyObject *val_obj;
+
+ if ((val_obj = PySequence_GetItem(seq, i)) == NULL)
+ return FALSE;
+
+ ok = sip_api_can_convert_to_type(val_obj, td,
+ SIP_NO_CONVERTORS|SIP_NOT_NONE);
+
+ Py_DECREF(val_obj);
+
+ if (!ok)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Convert a Python sequence to an array that has already "passed"
+ * canConvertFromSequence(). Return TRUE if the conversion was successful.
+ */
+static int convertFromSequence(PyObject *seq, const sipTypeDef *td,
+ void **array, SIP_SSIZE_T *nr_elem)
+{
+ int iserr = 0;
+ SIP_SSIZE_T i, size = PySequence_Size(seq);
+ sipArrayFunc array_helper;
+ sipAssignFunc assign_helper;
+ void *array_mem;
+
+ /* Get the type's helpers. */
+ if (sipTypeIsMapped(td))
+ {
+ array_helper = ((const sipMappedTypeDef *)td)->mtd_array;
+ assign_helper = ((const sipMappedTypeDef *)td)->mtd_assign;
+ }
+ else
+ {
+ array_helper = ((const sipClassTypeDef *)td)->ctd_array;
+ assign_helper = ((const sipClassTypeDef *)td)->ctd_assign;
+ }
+
+ assert(array_helper != NULL);
+ assert(assign_helper != NULL);
+
+ /*
+ * Create the memory for the array of values. Note that this will leak if
+ * there is an error.
+ */
+ array_mem = array_helper(size);
+
+ for (i = 0; i < size; ++i)
+ {
+ PyObject *val_obj;
+ void *val;
+
+ if ((val_obj = PySequence_GetItem(seq, i)) == NULL)
+ return FALSE;
+
+ val = sip_api_convert_to_type(val_obj, td, NULL,
+ SIP_NO_CONVERTORS|SIP_NOT_NONE, NULL, &iserr);
+
+ Py_DECREF(val_obj);
+
+ if (iserr)
+ return FALSE;
+
+ assign_helper(array_mem, i, val);
+ }
+
+ *array = array_mem;
+ *nr_elem = size;
+
+ return TRUE;
+}
+
+
+/*
+ * Convert an array of a type to a Python sequence.
+ */
+static PyObject *convertToSequence(void *array, SIP_SSIZE_T nr_elem,
+ const sipTypeDef *td)
+{
+ SIP_SSIZE_T i;
+ PyObject *seq;
+ sipCopyFunc copy_helper;
+
+ /* Get the type's copy helper. */
+ if (sipTypeIsMapped(td))
+ copy_helper = ((const sipMappedTypeDef *)td)->mtd_copy;
+ else
+ copy_helper = ((const sipClassTypeDef *)td)->ctd_copy;
+
+ assert(copy_helper != NULL);
+
+ if ((seq = PyTuple_New(nr_elem)) == NULL)
+ return NULL;
+
+ for (i = 0; i < nr_elem; ++i)
+ {
+ void *el = copy_helper(array, i);
+ PyObject *el_obj = sip_api_convert_from_new_type(el, td, NULL);
+
+ if (el_obj == NULL)
+ {
+ release(el, td, 0);
+ Py_DECREF(seq);
+ }
+
+ PyTuple_SET_ITEM(seq, i, el_obj);
+ }
+
+ return seq;
+}
+
+
+/*
+ * Carry out actions common to all dtors.
+ */
+void sip_api_common_dtor(sipSimpleWrapper *sipSelf)
+{
+ if (sipSelf != NULL && sipInterpreter != NULL)
+ {
+ PyObject *xtype, *xvalue, *xtb;
+
+ SIP_BLOCK_THREADS
+
+ /* We may be tidying up after an exception so preserve it. */
+ PyErr_Fetch(&xtype, &xvalue, &xtb);
+ callPyDtor(sipSelf);
+ PyErr_Restore(xtype, xvalue, xtb);
+
+ if (!sipNotInMap(sipSelf))
+ sipOMRemoveObject(&cppPyMap, sipSelf);
+
+ /* This no longer points to anything useful. */
+ sipSelf->u.cppPtr = NULL;
+
+ /*
+ * If C/C++ has a reference (and therefore no parent) then remove it.
+ * Otherwise remove the object from any parent.
+ */
+ if (sipCppHasRef(sipSelf))
+ {
+ sipResetCppHasRef(sipSelf);
+ Py_DECREF(sipSelf);
+ }
+ else if (PyObject_TypeCheck((PyObject *)sipSelf, (PyTypeObject *)&sipWrapper_Type))
+ removeFromParent((sipWrapper *)sipSelf);
+
+ SIP_UNBLOCK_THREADS
+ }
+}
+
+
+/*
+ * Call self.__dtor__() if it is implemented.
+ */
+static void callPyDtor(sipSimpleWrapper *self)
+{
+ sip_gilstate_t sipGILState;
+ char pymc = 0;
+ PyObject *meth;
+
+ meth = sip_api_is_py_method(&sipGILState, &pymc, self, NULL, "__dtor__");
+
+ if (meth != NULL)
+ {
+ PyObject *res = sip_api_call_method(0, meth, "", NULL);
+
+ Py_DECREF(meth);
+
+ /* Discard any result. */
+ Py_XDECREF(res);
+
+ /* Handle any error the best we can. */
+ if (PyErr_Occurred())
+ PyErr_Print();
+
+ SIP_RELEASE_GIL(sipGILState);
+ }
+}
+
+
+/*
+ * Add a wrapper to it's parent owner. The wrapper must not currently have a
+ * parent and, therefore, no siblings.
+ */
+static void addToParent(sipWrapper *self, sipWrapper *owner)
+{
+ if (owner->first_child != NULL)
+ {
+ self->sibling_next = owner->first_child;
+ owner->first_child->sibling_prev = self;
+ }
+
+ owner->first_child = self;
+ self->parent = owner;
+
+ /*
+ * The owner holds a real reference so that the cyclic garbage collector
+ * works properly.
+ */
+ Py_INCREF((sipSimpleWrapper *)self);
+}
+
+
+/*
+ * Remove a wrapper from it's parent if it has one.
+ */
+static void removeFromParent(sipWrapper *self)
+{
+ if (self->parent != NULL)
+ {
+ if (self->parent->first_child == self)
+ self->parent->first_child = self->sibling_next;
+
+ if (self->sibling_next != NULL)
+ self->sibling_next->sibling_prev = self->sibling_prev;
+
+ if (self->sibling_prev != NULL)
+ self->sibling_prev->sibling_next = self->sibling_next;
+
+ self->parent = NULL;
+ self->sibling_next = NULL;
+ self->sibling_prev = NULL;
+
+ /*
+ * We must do this last, after all the pointers are correct, because
+ * this is used by the clear slot.
+ */
+ Py_DECREF((sipSimpleWrapper *)self);
+ }
+}
+
+
+/*
+ * Convert a sequence index. Return the index or a negative value if there was
+ * an error.
+ */
+static SIP_SSIZE_T sip_api_convert_from_sequence_index(SIP_SSIZE_T idx,
+ SIP_SSIZE_T len)
+{
+ /* Negative indices start from the other end. */
+ if (idx < 0)
+ idx = len + idx;
+
+ if (idx < 0 || idx >= len)
+ {
+ PyErr_Format(PyExc_IndexError, "sequence index out of range");
+ return -1;
+ }
+
+ return idx;
+}
+
+
+/*
+ * Return a tuple of the base classes of a type that has no explicit
+ * super-type.
+ */
+static PyObject *getDefaultBases(void)
+{
+ static PyObject *default_bases = NULL;
+
+ /* Only do this once. */
+ if (default_bases == NULL)
+ {
+#if PY_VERSION_HEX >= 0x02040000
+ default_bases = PyTuple_Pack(1, (PyObject *)&sipWrapper_Type);
+#else
+ default_bases = Py_BuildValue("(O)", &sipWrapper_Type);
+#endif
+
+ if (default_bases == NULL)
+ return NULL;
+ }
+
+ Py_INCREF(default_bases);
+
+ return default_bases;
+}
+
+
+/*
+ * Return the dictionary of a type.
+ */
+static PyObject *getScopeDict(sipTypeDef *td, PyObject *mod_dict,
+ sipExportedModuleDef *client)
+{
+ /*
+ * Initialise the scoping type if necessary. It will always be in the
+ * same module if it needs doing.
+ */
+ if (sipTypeIsMapped(td))
+ {
+ if (createMappedType(client, (sipMappedTypeDef *)td, mod_dict) < 0)
+ return NULL;
+
+ /* Check that the mapped type can act as a container. */
+ assert(sipTypeAsPyTypeObject(td) != NULL);
+ }
+ else
+ {
+ if (createClassType(client, (sipClassTypeDef *)td, mod_dict) < 0)
+ return NULL;
+ }
+
+ return (sipTypeAsPyTypeObject(td))->tp_dict;
+}
+
+
+/*
+ * Create a container type and return a borrowed reference to it.
+ */
+static PyObject *createContainerType(sipContainerDef *cod, sipTypeDef *td,
+ PyObject *bases, PyObject *metatype, PyObject *mod_dict,
+ sipExportedModuleDef *client)
+{
+ PyObject *py_type, *scope_dict, *typedict, *name, *args;
+
+ /* Get the dictionary to place the type in. */
+ if (cod->cod_scope.sc_flag)
+ {
+ scope_dict = mod_dict;
+ }
+ else if ((scope_dict = getScopeDict(getGeneratedType(&cod->cod_scope, client), mod_dict, client)) == NULL)
+ goto reterr;
+
+ /* Create the type dictionary. */
+ if ((typedict = createTypeDict(client->em_nameobj)) == NULL)
+ goto reterr;
+
+ /* Create an object corresponding to the type name. */
+#if PY_MAJOR_VERSION >= 3
+ name = PyUnicode_FromString(sipPyNameOfContainer(cod, td));
+#else
+ name = PyString_FromString(sipPyNameOfContainer(cod, td));
+#endif
+
+ if (name == NULL)
+ goto reldict;
+
+ /* Create the type by calling the metatype. */
+#if PY_VERSION_HEX >= 0x02040000
+ args = PyTuple_Pack(3, name, bases, typedict);
+#else
+ args = Py_BuildValue("OOO", name, bases, typedict);
+#endif
+
+ if (args == NULL)
+ goto relname;
+
+ /* Pass the type via the back door. */
+ currentType = td;
+
+ if ((py_type = PyObject_Call(metatype, args, NULL)) == NULL)
+ goto relargs;
+
+ /* Add the type to the "parent" dictionary. */
+ if (PyDict_SetItem(scope_dict, name, py_type) < 0)
+ goto reltype;
+
+ Py_DECREF(args);
+ Py_DECREF(name);
+ Py_DECREF(typedict);
+
+ return py_type;
+
+ /* Unwind on error. */
+
+reltype:
+ Py_DECREF(py_type);
+
+relargs:
+ Py_DECREF(args);
+
+relname:
+ Py_DECREF(name);
+
+reldict:
+ Py_DECREF(typedict);
+
+reterr:
+ currentType = NULL;
+ return NULL;
+}
+
+
+/*
+ * Create a single class type object.
+ */
+static int createClassType(sipExportedModuleDef *client, sipClassTypeDef *ctd,
+ PyObject *mod_dict)
+{
+ PyObject *bases, *metatype, *py_type;
+ sipEncodedTypeDef *sup;
+
+ /* Handle the trivial case where we have already been initialised. */
+ if (ctd->ctd_base.td_module != NULL)
+ return 0;
+
+ /* Set this up now to gain access to the string pool. */
+ ctd->ctd_base.td_module = client;
+
+ /* Create the tuple of super-types. */
+ if ((sup = ctd->ctd_supers) == NULL)
+ {
+ if (ctd->ctd_supertype < 0)
+ {
+ bases = getDefaultBases();
+ }
+ else
+ {
+ PyObject *supertype;
+ const char *supertype_name = sipNameFromPool(client,
+ ctd->ctd_supertype);
+
+ if ((supertype = findPyType(supertype_name)) == NULL)
+ goto reterr;
+
+#if PY_VERSION_HEX >= 0x02040000
+ bases = PyTuple_Pack(1, supertype);
+#else
+ bases = Py_BuildValue("(O)", supertype);
+#endif
+ }
+
+ if (bases == NULL)
+ goto reterr;
+ }
+ else
+ {
+ int i, nrsupers = 0;
+
+ do
+ ++nrsupers;
+ while (!sup++->sc_flag);
+
+ if ((bases = PyTuple_New(nrsupers)) == NULL)
+ goto reterr;
+
+ for (sup = ctd->ctd_supers, i = 0; i < nrsupers; ++i, ++sup)
+ {
+ PyObject *st;
+ sipTypeDef *sup_td = getGeneratedType(sup, client);
+
+ /*
+ * Initialise the super-class if necessary. It will always be in
+ * the same module if it needs doing.
+ */
+ if (createClassType(client, (sipClassTypeDef *)sup_td, mod_dict) < 0)
+ goto relbases;
+
+ st = (PyObject *)sipTypeAsPyTypeObject(sup_td);
+
+ Py_INCREF(st);
+ PyTuple_SET_ITEM(bases, i, st);
+ }
+ }
+
+ /*
+ * Use the explicit meta-type if there is one, otherwise use the meta-type
+ * of the first super-type.
+ */
+ if (ctd->ctd_metatype >= 0)
+ {
+ const char *metatype_name = sipNameFromPool(client, ctd->ctd_metatype);
+
+ if ((metatype = findPyType(metatype_name)) == NULL)
+ goto relbases;
+ }
+ else
+ metatype = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(bases, 0));
+
+ if ((py_type = createContainerType(&ctd->ctd_container, (sipTypeDef *)ctd, bases, metatype, mod_dict, client)) == NULL)
+ goto relbases;
+
+ /* Handle the pickle function. */
+ if (ctd->ctd_pickle != NULL)
+ {
+ static PyMethodDef md = {
+ "_pickle_type", pickle_type, METH_NOARGS, NULL
+ };
+
+ if (setReduce((PyTypeObject *)py_type, &md) < 0)
+ goto reltype;
+ }
+
+ /* We can now release our references. */
+ Py_DECREF(bases);
+
+ return 0;
+
+ /* Unwind after an error. */
+
+reltype:
+ Py_DECREF(py_type);
+
+relbases:
+ Py_DECREF(bases);
+
+reterr:
+ ctd->ctd_base.td_module = NULL;
+ return -1;
+}
+
+
+/*
+ * Create a single mapped type object.
+ */
+static int createMappedType(sipExportedModuleDef *client,
+ sipMappedTypeDef *mtd, PyObject *mod_dict)
+{
+ PyObject *bases;
+
+ /* Handle the trivial case where we have already been initialised. */
+ if (mtd->mtd_base.td_module != NULL)
+ return 0;
+
+ /* Set this up now to gain access to the string pool. */
+ mtd->mtd_base.td_module = client;
+
+ /* Create the tuple of super-types. */
+ if ((bases = getDefaultBases()) == NULL)
+ goto reterr;
+
+ if (createContainerType(&mtd->mtd_container, (sipTypeDef *)mtd, bases, (PyObject *)&sipWrapperType_Type, mod_dict, client) == NULL)
+ goto relbases;
+
+ /* We can now release our references. */
+ Py_DECREF(bases);
+
+ return 0;
+
+ /* Unwind after an error. */
+
+relbases:
+ Py_DECREF(bases);
+
+reterr:
+ mtd->mtd_base.td_module = NULL;
+ return -1;
+}
+
+
+/*
+ * Return the module definition for a named module.
+ */
+static sipExportedModuleDef *getModule(PyObject *mname_obj)
+{
+ PyObject *mod;
+ sipExportedModuleDef *em;
+
+ /* Make sure the module is imported. */
+ if ((mod = PyImport_Import(mname_obj)) == NULL)
+ return NULL;
+
+ /* Find the module definition. */
+ for (em = moduleList; em != NULL; em = em->em_next)
+#if PY_MAJOR_VERSION >= 3
+ if (PyUnicode_Compare(mname_obj, em->em_nameobj) == 0)
+#else
+ if (strcmp(PyString_AS_STRING(mname_obj), sipNameOfModule(em)) == 0)
+#endif
+ break;
+
+ Py_DECREF(mod);
+
+ if (em == NULL)
+ {
+#if PY_MAJOR_VERSION >= 3
+ PyErr_Format(PyExc_SystemError, "unable to find to find module: %U",
+ mname_obj);
+#else
+ PyErr_Format(PyExc_SystemError, "unable to find to find module: %s",
+ PyString_AS_STRING(mname_obj));
+#endif
+ }
+
+ return em;
+}
+
+
+/*
+ * The type unpickler.
+ */
+static PyObject *unpickle_type(PyObject *ignore, PyObject *args)
+{
+ PyObject *mname_obj, *init_args;
+ const char *tname;
+ sipExportedModuleDef *em;
+ int i;
+
+ if (!PyArg_ParseTuple(args,
+#if PY_MAJOR_VERSION >= 3
+ "UsO!:_unpickle_type",
+#else
+ "SsO!:_unpickle_type",
+#endif
+ &mname_obj, &tname, &PyTuple_Type, &init_args))
+ return NULL;
+
+ /* Get the module definition. */
+ if ((em = getModule(mname_obj)) == NULL)
+ return NULL;
+
+ /* Find the class type object. */
+ for (i = 0; i < em->em_nrtypes; ++i)
+ {
+ sipTypeDef *td = em->em_types[i];
+
+ if (td != NULL && !sipTypeIsStub(td) && sipTypeIsClass(td))
+ {
+ const char *pyname = sipPyNameOfContainer(
+ &((sipClassTypeDef *)td)->ctd_container, td);
+
+ if (strcmp(pyname, tname) == 0)
+ return PyObject_CallObject((PyObject *)sipTypeAsPyTypeObject(td), init_args);
+ }
+ }
+
+ PyErr_Format(PyExc_SystemError, "unable to find to find type: %s", tname);
+
+ return NULL;
+}
+
+
+/*
+ * The type pickler.
+ */
+static PyObject *pickle_type(PyObject *obj, PyObject *ignore)
+{
+ sipExportedModuleDef *em;
+
+ /* Find the type definition and defining module. */
+ for (em = moduleList; em != NULL; em = em->em_next)
+ {
+ int i;
+
+ for (i = 0; i < em->em_nrtypes; ++i)
+ {
+ sipTypeDef *td = em->em_types[i];
+
+ if (td != NULL && !sipTypeIsStub(td) && sipTypeIsClass(td))
+ if (sipTypeAsPyTypeObject(td) == Py_TYPE(obj))
+ {
+ PyObject *init_args;
+ sipClassTypeDef *ctd = (sipClassTypeDef *)td;
+ const char *pyname = sipPyNameOfContainer(&ctd->ctd_container, td);
+
+ /*
+ * Ask the handwritten pickle code for the tuple of
+ * arguments that will recreate the object.
+ */
+ init_args = ctd->ctd_pickle(sip_api_get_cpp_ptr((sipSimpleWrapper *)obj, NULL));
+
+ if (!PyTuple_Check(init_args))
+ {
+ PyErr_Format(PyExc_TypeError,
+ "%%PickleCode for type %s.%s did not return a tuple",
+ sipNameOfModule(em), pyname);
+
+ return NULL;
+ }
+
+ return Py_BuildValue("O(OsN)", type_unpickler,
+ em->em_nameobj, pyname, init_args);
+ }
+ }
+ }
+
+ /* We should never get here. */
+ PyErr_Format(PyExc_SystemError, "attempt to pickle unknown type '%s'",
+ Py_TYPE(obj)->tp_name);
+
+ return NULL;
+}
+
+
+/*
+ * The enum unpickler.
+ */
+static PyObject *unpickle_enum(PyObject *ignore, PyObject *args)
+{
+ PyObject *mname_obj, *evalue_obj;
+ const char *ename;
+ sipExportedModuleDef *em;
+ int i;
+
+ if (!PyArg_ParseTuple(args,
+#if PY_MAJOR_VERSION >= 3
+ "UsO:_unpickle_enum",
+#else
+ "SsO:_unpickle_enum",
+#endif
+ &mname_obj, &ename, &evalue_obj))
+ return NULL;
+
+ /* Get the module definition. */
+ if ((em = getModule(mname_obj)) == NULL)
+ return NULL;
+
+ /* Find the enum type object. */
+ for (i = 0; i < em->em_nrtypes; ++i)
+ {
+ sipTypeDef *td = em->em_types[i];
+
+ if (td != NULL && !sipTypeIsStub(td) && sipTypeIsEnum(td))
+ if (strcmp(sipPyNameOfEnum((sipEnumTypeDef *)td), ename) == 0)
+ return PyObject_CallFunctionObjArgs((PyObject *)sipTypeAsPyTypeObject(td), evalue_obj, NULL);
+ }
+
+ PyErr_Format(PyExc_SystemError, "unable to find to find enum: %s", ename);
+
+ return NULL;
+}
+
+
+/*
+ * The enum pickler.
+ */
+static PyObject *pickle_enum(PyObject *obj, PyObject *ignore)
+{
+ sipTypeDef *td = ((sipEnumTypeObject *)Py_TYPE(obj))->type;
+
+ return Py_BuildValue("O(Osi)", enum_unpickler, td->td_module->em_nameobj,
+ sipPyNameOfEnum((sipEnumTypeDef *)td),
+#if PY_MAJOR_VERSION >= 3
+ (int)PyLong_AS_LONG(obj)
+#else
+ (int)PyInt_AS_LONG(obj)
+#endif
+ );
+}
+
+
+/*
+ * Set the __reduce__method for a type.
+ */
+static int setReduce(PyTypeObject *type, PyMethodDef *pickler)
+{
+ static PyObject *rstr = NULL;
+ PyObject *descr;
+ int rc;
+
+ if (objectify("__reduce__", &rstr) < 0)
+ return -1;
+
+ /* Create the method descripter. */
+ if ((descr = PyDescr_NewMethod(type, pickler)) == NULL)
+ return -1;
+
+ /*
+ * Save the method. Note that we don't use PyObject_SetAttr() as we want
+ * to bypass any lazy attribute loading (which may not be safe yet).
+ */
+ rc = PyType_Type.tp_setattro((PyObject *)type, rstr, descr);
+
+ Py_DECREF(descr);
+
+ return rc;
+}
+
+
+/*
+ * Create an enum type object.
+ */
+static int createEnumType(sipExportedModuleDef *client, sipEnumTypeDef *etd,
+ PyObject *mod_dict)
+{
+ static PyObject *bases = NULL;
+ PyObject *name, *typedict, *args, *dict;
+ PyTypeObject *py_type;
+
+ etd->etd_base.td_module = client;
+
+ /* Get the dictionary into which the type will be placed. */
+ if (etd->etd_scope < 0)
+ dict = mod_dict;
+ else if ((dict = getScopeDict(client->em_types[etd->etd_scope], mod_dict, client)) == NULL)
+ goto reterr;
+
+ /* Create the base type tuple if it hasn't already been done. */
+ if (bases == NULL)
+ {
+#if PY_MAJOR_VERSION >= 3
+ bases = PyTuple_Pack(1, (PyObject *)&PyLong_Type);
+#elif PY_VERSION_HEX >= 0x02040000
+ bases = PyTuple_Pack(1, (PyObject *)&PyInt_Type);
+#else
+ bases = Py_BuildValue("(O)", &PyInt_Type);
+#endif
+
+ if (bases == NULL)
+ goto reterr;
+ }
+
+ /* Create an object corresponding to the type name. */
+#if PY_MAJOR_VERSION >= 3
+ name = PyUnicode_FromString(sipPyNameOfEnum(etd));
+#else
+ name = PyString_FromString(sipPyNameOfEnum(etd));
+#endif
+
+ if (name == NULL)
+ goto reterr;
+
+ /* Create the type dictionary. */
+ if ((typedict = createTypeDict(client->em_nameobj)) == NULL)
+ goto relname;
+
+ /* Create the type by calling the metatype. */
+#if PY_VERSION_HEX >= 0x02040000
+ args = PyTuple_Pack(3, name, bases, typedict);
+#else
+ args = Py_BuildValue("OOO", name, bases, typedict);
+#endif
+
+ Py_DECREF(typedict);
+
+ if (args == NULL)
+ goto relname;
+
+ /* Pass the type via the back door. */
+ currentType = &etd->etd_base;
+
+ py_type = (PyTypeObject *)PyObject_Call((PyObject *)&sipEnumType_Type, args, NULL);
+
+ Py_DECREF(args);
+
+ if (py_type == NULL)
+ goto relname;
+
+ /* Add the type to the "parent" dictionary. */
+ if (PyDict_SetItem(dict, name, (PyObject *)py_type) < 0)
+ {
+ Py_DECREF((PyObject *)py_type);
+ goto relname;
+ }
+
+ /* We can now release our remaining references. */
+ Py_DECREF(name);
+
+ return 0;
+
+ /* Unwind after an error. */
+
+relname:
+ Py_DECREF(name);
+
+reterr:
+ etd->etd_base.td_module = client;
+ return -1;
+}
+
+
+/*
+ * Create a type dictionary for dynamic type being created in the module with
+ * the specified name.
+ */
+static PyObject *createTypeDict(PyObject *mname)
+{
+ static PyObject *mstr = NULL;
+ PyObject *dict;
+
+ if (objectify("__module__", &mstr) < 0)
+ return NULL;
+
+ /* Create the dictionary. */
+ if ((dict = PyDict_New()) == NULL)
+ return NULL;
+
+ /* We need to set the module name as an attribute for dynamic types. */
+ if (PyDict_SetItem(dict, mstr, mname) < 0)
+ {
+ Py_DECREF(dict);
+ return NULL;
+ }
+
+ return dict;
+}
+
+
+/*
+ * Convert an ASCII string to a Python object if it hasn't already been done.
+ */
+static int objectify(const char *s, PyObject **objp)
+{
+ if (*objp == NULL)
+ {
+#if PY_MAJOR_VERSION >= 3
+ *objp = PyUnicode_FromString(s);
+#else
+ *objp = PyString_FromString(s);
+#endif
+
+ if (*objp == NULL)
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Add a set of static instances to a dictionary.
+ */
+static int addInstances(PyObject *dict, sipInstancesDef *id)
+{
+ if (id->id_type != NULL && addTypeInstances(dict, id->id_type) < 0)
+ return -1;
+
+ if (id->id_voidp != NULL && addVoidPtrInstances(dict,id->id_voidp) < 0)
+ return -1;
+
+ if (id->id_char != NULL && addCharInstances(dict,id->id_char) < 0)
+ return -1;
+
+ if (id->id_string != NULL && addStringInstances(dict,id->id_string) < 0)
+ return -1;
+
+ if (id->id_int != NULL && addIntInstances(dict, id->id_int) < 0)
+ return -1;
+
+ if (id->id_long != NULL && addLongInstances(dict,id->id_long) < 0)
+ return -1;
+
+ if (id->id_ulong != NULL && addUnsignedLongInstances(dict, id->id_ulong) < 0)
+ return -1;
+
+ if (id->id_llong != NULL && addLongLongInstances(dict, id->id_llong) < 0)
+ return -1;
+
+ if (id->id_ullong != NULL && addUnsignedLongLongInstances(dict, id->id_ullong) < 0)
+ return -1;
+
+ if (id->id_double != NULL && addDoubleInstances(dict,id->id_double) < 0)
+ return -1;
+
+ return 0;
+}
+
+
+/*
+ * Get "self" from the argument tuple for a method called as
+ * Class.Method(self, ...) rather than self.Method(...).
+ */
+static int getSelfFromArgs(sipTypeDef *td, PyObject *args, int argnr,
+ sipSimpleWrapper **selfp)
+{
+ PyObject *self;
+
+ /* Get self from the argument tuple. */
+
+ if (argnr >= PyTuple_GET_SIZE(args))
+ return FALSE;
+
+ self = PyTuple_GET_ITEM(args, argnr);
+
+ if (!PyObject_TypeCheck(self, sipTypeAsPyTypeObject(td)))
+ return FALSE;
+
+ *selfp = (sipSimpleWrapper *)self;
+
+ return TRUE;
+}
+
+
+/*
+ * Populate a container's type dictionary.
+ */
+static int add_lazy_container_attrs(sipTypeDef *td, sipContainerDef *cod,
+ PyObject *dict)
+{
+ int i;
+ PyMethodDef *pmd;
+ sipEnumMemberDef *enm;
+ sipVariableDef *vd;
+
+ /* Do the methods. */
+ pmd = cod->cod_methods;
+
+ for (i = 0; i < cod->cod_nrmethods; ++i)
+ {
+ int rc;
+ PyObject *descr;
+
+ if ((descr = sipMethodDescr_New(pmd)) == NULL)
+ return -1;
+
+ rc = PyDict_SetItemString(dict, pmd->ml_name, descr);
+
+ Py_DECREF(descr);
+
+ if (rc < 0)
+ return -1;
+
+ ++pmd;
+ }
+
+ /* Do the enum members. */
+ enm = cod->cod_enummembers;
+
+ for (i = 0; i < cod->cod_nrenummembers; ++i)
+ {
+ int rc;
+ PyObject *val;
+
+ if ((val = createEnumMember(td, enm)) == NULL)
+ return -1;
+
+ rc = PyDict_SetItemString(dict, enm->em_name, val);
+
+ Py_DECREF(val);
+
+ if (rc < 0)
+ return -1;
+
+ ++enm;
+ }
+
+ /* Do the variables. */
+ vd = cod->cod_variables;
+
+ for (i = 0; i < cod->cod_nrvariables; ++i)
+ {
+ int rc;
+ PyObject *descr;
+
+ if ((descr = sipVariableDescr_New(vd, td, cod)) == NULL)
+ return -1;
+
+ rc = PyDict_SetItemString(dict, vd->vd_name, descr);
+
+ Py_DECREF(descr);
+
+ if (rc < 0)
+ return -1;
+
+ ++vd;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Populate a type dictionary with all lazy attributes if it hasn't already
+ * been done.
+ */
+static int add_lazy_attrs(sipTypeDef *td)
+{
+ sipWrapperType *wt = (sipWrapperType *)sipTypeAsPyTypeObject(td);
+ PyObject *dict;
+ sipAttrGetter *ag;
+
+ /* Handle the trivial case. */
+ if (wt->dict_complete)
+ return 0;
+
+ dict = ((PyTypeObject *)wt)->tp_dict;
+
+ if (sipTypeIsMapped(td))
+ {
+ if (add_lazy_container_attrs(td, &((sipMappedTypeDef *)td)->mtd_container, dict) < 0)
+ return -1;
+ }
+ else
+ {
+ sipClassTypeDef *nsx;
+
+ /* Search the possible linked list of namespace extenders. */
+ for (nsx = (sipClassTypeDef *)td; nsx != NULL; nsx = nsx->ctd_nsextender)
+ if (add_lazy_container_attrs((sipTypeDef *)nsx, &nsx->ctd_container, dict) < 0)
+ return -1;
+ }
+
+ /*
+ * Get any lazy attributes from registered getters. This must be done last
+ * to allow any existing attributes to be replaced.
+ */
+ for (ag = sipAttrGetters; ag != NULL; ag = ag->next)
+ if (ag->type == NULL || PyType_IsSubtype((PyTypeObject *)wt, ag->type))
+ if (ag->getter(td, dict) < 0)
+ return -1;
+
+ wt->dict_complete = TRUE;
+
+ return 0;
+}
+
+
+/*
+ * Populate the type dictionary and all its super-types.
+ */
+static int add_all_lazy_attrs(sipTypeDef *td)
+{
+ if (td == NULL)
+ return 0;
+
+ if (add_lazy_attrs(td) < 0)
+ return -1;
+
+ if (sipTypeIsClass(td))
+ {
+ sipClassTypeDef *ctd = (sipClassTypeDef *)td;
+ sipEncodedTypeDef *sup;
+
+ if ((sup = ctd->ctd_supers) != NULL)
+ do
+ {
+ sipTypeDef *sup_td = getGeneratedType(sup, td->td_module);
+
+ if (add_all_lazy_attrs(sup_td) < 0)
+ return -1;
+ }
+ while (!sup++->sc_flag);
+ }
+
+ return 0;
+}
+
+
+/*
+ * Return the generated type structure corresponding to the given Python type
+ * object.
+ */
+static const sipTypeDef *sip_api_type_from_py_type_object(PyTypeObject *py_type)
+{
+ if (PyObject_TypeCheck((PyObject *)py_type, &sipWrapperType_Type))
+ return ((sipWrapperType *)py_type)->type;
+
+ if (PyObject_TypeCheck((PyObject *)py_type, &sipEnumType_Type))
+ return ((sipEnumTypeObject *)py_type)->type;
+
+ return NULL;
+}
+
+
+/*
+ * Return the generated type structure corresponding to the scope of the given
+ * type.
+ */
+static const sipTypeDef *sip_api_type_scope(const sipTypeDef *td)
+{
+ if (sipTypeIsEnum(td))
+ {
+ const sipEnumTypeDef *etd = (const sipEnumTypeDef *)td;
+
+ if (etd->etd_scope >= 0)
+ return td->td_module->em_types[etd->etd_scope];
+ }
+ else
+ {
+ const sipContainerDef *cod;
+
+ if (sipTypeIsMapped(td))
+ cod = &((const sipMappedTypeDef *)td)->mtd_container;
+ else
+ cod = &((const sipClassTypeDef *)td)->ctd_container;
+
+ if (!cod->cod_scope.sc_flag)
+ return getGeneratedType(&cod->cod_scope, td->td_module);
+ }
+
+ return NULL;
+}
+
+
+/*
+ * Return TRUE if an object can be converted to a named enum.
+ */
+static int sip_api_can_convert_to_enum(PyObject *obj, const sipTypeDef *td)
+{
+ assert(sipTypeIsEnum(td));
+
+ /* If the object is an enum then it must be the right enum. */
+ if (PyObject_TypeCheck((PyObject *)Py_TYPE(obj), &sipEnumType_Type))
+ return (PyObject_TypeCheck(obj, sipTypeAsPyTypeObject(td)));
+
+#if PY_MAJOR_VERSION >= 3
+ return PyLong_Check(obj);
+#else
+ return PyInt_Check(obj);
+#endif
+}
+
+
+/*
+ * Create a Python object for an enum member.
+ */
+static PyObject *createEnumMember(sipTypeDef *td, sipEnumMemberDef *enm)
+{
+ if (enm->em_enum < 0)
+#if PY_MAJOR_VERSION >= 3
+ return PyLong_FromLong(enm->em_val);
+#else
+ return PyInt_FromLong(enm->em_val);
+#endif
+
+ return sip_api_convert_from_enum(enm->em_val,
+ td->td_module->em_types[enm->em_enum]);
+}
+
+
+/*
+ * Create a Python object for a member of a named enum.
+ */
+static PyObject *sip_api_convert_from_enum(int eval, const sipTypeDef *td)
+{
+ assert(sipTypeIsEnum(td));
+
+ return PyObject_CallFunction((PyObject *)sipTypeAsPyTypeObject(td), "(i)",
+ eval);
+}
+
+
+/*
+ * Register a getter for unknown attributes.
+ */
+static int sip_api_register_attribute_getter(const sipTypeDef *td,
+ sipAttrGetterFunc getter)
+{
+ sipAttrGetter *ag = sip_api_malloc(sizeof (sipAttrGetter));
+
+ if (ag == NULL)
+ return -1;
+
+ ag->type = sipTypeAsPyTypeObject(td);
+ ag->getter = getter;
+ ag->next = sipAttrGetters;
+
+ sipAttrGetters = ag;
+
+ return 0;
+}
+
+
+/*
+ * Report a function with invalid argument types.
+ */
+static void sip_api_no_function(PyObject *parseErr, const char *func,
+ const char *doc)
+{
+ sip_api_no_method(parseErr, NULL, func, doc);
+}
+
+
+/*
+ * Report a method/function/signal with invalid argument types.
+ */
+static void sip_api_no_method(PyObject *parseErr, const char *scope,
+ const char *method, const char *doc)
+{
+ const char *sep = ".";
+
+ if (scope == NULL)
+ scope = ++sep;
+
+ if (parseErr == NULL)
+ {
+ /*
+ * If we have got this far without trying a parse then there must be no
+ * overloads.
+ */
+ PyErr_Format(PyExc_TypeError, "%s%s%s() is a private method", scope,
+ sep, method);
+ }
+ else if (PyList_Check(parseErr))
+ {
+ PyObject *exc;
+
+ /* There is an entry for each overload that was tried. */
+ if (PyList_GET_SIZE(parseErr) == 1)
+ {
+ PyObject *detail = detail_FromFailure(
+ PyList_GET_ITEM(parseErr, 0));
+
+ if (detail != NULL)
+ {
+ if (doc != NULL)
+ {
+ PyObject *doc_obj = signature_FromDocstring(doc, 0);
+
+ if (doc_obj != NULL)
+ {
+#if PY_MAJOR_VERSION >= 3
+ exc = PyUnicode_FromFormat("%U: %U", doc_obj, detail);
+#else
+ exc = PyString_FromFormat("%s: %s",
+ PyString_AS_STRING(doc_obj),
+ PyString_AS_STRING(detail));
+#endif
+
+ Py_DECREF(doc_obj);
+ }
+ else
+ {
+ exc = NULL;
+ }
+ }
+ else
+ {
+#if PY_MAJOR_VERSION >= 3
+ exc = PyUnicode_FromFormat("%s%s%s(): %U", scope, sep,
+ method, detail);
+#else
+ exc = PyString_FromFormat("%s%s%s(): %s", scope, sep,
+ method, PyString_AS_STRING(detail));
+#endif
+ }
+
+ Py_DECREF(detail);
+ }
+ else
+ {
+ exc = NULL;
+ }
+ }
+ else
+ {
+ static const char *summary = "arguments did not match any overloaded call:";
+
+ SIP_SSIZE_T i;
+
+ if (doc != NULL)
+ {
+#if PY_MAJOR_VERSION >= 3
+ exc = PyUnicode_FromString(summary);
+#else
+ exc = PyString_FromString(summary);
+#endif
+ }
+ else
+ {
+#if PY_MAJOR_VERSION >= 3
+ exc = PyUnicode_FromFormat("%s%s%s(): %s", scope, sep, method,
+ summary);
+#else
+ exc = PyString_FromFormat("%s%s%s(): %s", scope, sep, method,
+ summary);
+#endif
+ }
+
+ for (i = 0; i < PyList_GET_SIZE(parseErr); ++i)
+ {
+ PyObject *failure;
+ PyObject *detail = detail_FromFailure(
+ PyList_GET_ITEM(parseErr, i));
+
+ if (detail != NULL)
+ {
+ if (doc != NULL)
+ {
+ PyObject *doc_obj = signature_FromDocstring(doc, i);
+
+ if (doc_obj != NULL)
+ {
+#if PY_MAJOR_VERSION >= 3
+ failure = PyUnicode_FromFormat("\n %U: %U",
+ doc_obj, detail);
+#else
+ failure = PyString_FromFormat("\n %s: %s",
+ PyString_AS_STRING(doc_obj),
+ PyString_AS_STRING(detail));
+#endif
+
+ Py_DECREF(doc_obj);
+ }
+ else
+ {
+ Py_XDECREF(exc);
+ exc = NULL;
+ break;
+ }
+ }
+ else
+ {
+#if PY_MAJOR_VERSION >= 3
+ failure = PyUnicode_FromFormat("\n overload %zd: %U",
+ i + 1, detail);
+#elif PY_VERSION_HEX >= 0x02050000
+ failure = PyString_FromFormat("\n overload %zd: %s",
+ i + 1, PyString_AS_STRING(detail));
+#else
+ failure = PyString_FromFormat("\n overload %d: %s",
+ i + 1, PyString_AS_STRING(detail));
+#endif
+ }
+
+ Py_DECREF(detail);
+
+#if PY_MAJOR_VERSION >= 3
+ PyUnicode_AppendAndDel(&exc, failure);
+#else
+ PyString_ConcatAndDel(&exc, failure);
+#endif
+ }
+ else
+ {
+ Py_XDECREF(exc);
+ exc = NULL;
+ break;
+ }
+ }
+ }
+
+ if (exc != NULL)
+ {
+ PyErr_SetObject(PyExc_TypeError, exc);
+ Py_DECREF(exc);
+ }
+ }
+ else
+ {
+ /*
+ * None is used as a marker to say that an exception has already been
+ * raised. This won't show which overload we were parsing but it
+ * doesn't really matter as it is a fundamental problem rather than a
+ * user error.
+ */
+ assert(parseErr == Py_None);
+ }
+
+ Py_XDECREF(parseErr);
+}
+
+
+/*
+ * Return a string/unicode object extracted from a particular line of a
+ * docstring.
+ */
+static PyObject *signature_FromDocstring(const char *doc, SIP_SSIZE_T line)
+{
+ const char *eol;
+ SIP_SSIZE_T size = 0;
+
+ /*
+ * Find the start of the line. If there is a non-default versioned
+ * overload that has been enabled then it won't have an entry in the
+ * docstring. This means that the returned signature may be incorrect.
+ */
+ while (line-- > 0)
+ {
+ const char *next = strchr(doc, '\n');
+
+ if (next == NULL)
+ break;
+
+ doc = next + 1;
+ }
+
+ /* Find the last closing parenthesis. */
+ for (eol = doc; *eol != '\n' && *eol != '\0'; ++eol)
+ if (*eol == ')')
+ size = eol - doc + 1;
+
+#if PY_MAJOR_VERSION >= 3
+ return PyUnicode_FromStringAndSize(doc, size);
+#else
+ return PyString_FromStringAndSize(doc, size);
+#endif
+}
+
+
+/*
+ * Return a string/unicode object that describes the given failure.
+ */
+static PyObject *detail_FromFailure(PyObject *failure_obj)
+{
+ sipParseFailure *failure;
+ PyObject *detail;
+
+#if defined(SIP_USE_PYCAPSULE)
+ failure = (sipParseFailure *)PyCapsule_GetPointer(failure_obj, NULL);
+#else
+ failure = (sipParseFailure *)PyCObject_AsVoidPtr(failure_obj);
+#endif
+
+ switch (failure->reason)
+ {
+ case Unbound:
+#if PY_MAJOR_VERSION >= 3
+ detail = PyUnicode_FromFormat(
+ "first argument of unbound method must have type '%s'",
+ failure->detail_str);
+#else
+ detail = PyString_FromFormat(
+ "first argument of unbound method must have type '%s'",
+ failure->detail_str);
+#endif
+ break;
+
+ case TooFew:
+#if PY_MAJOR_VERSION >= 3
+ detail = PyUnicode_FromString("not enough arguments");
+#else
+ detail = PyString_FromString("not enough arguments");
+#endif
+ break;
+
+ case TooMany:
+#if PY_MAJOR_VERSION >= 3
+ detail = PyUnicode_FromString("too many arguments");
+#else
+ detail = PyString_FromString("too many arguments");
+#endif
+ break;
+
+ case KeywordNotString:
+#if PY_MAJOR_VERSION >= 3
+ detail = PyUnicode_FromFormat(
+ "%S keyword argument name is not a string",
+ failure->detail_obj);
+#else
+ {
+ PyObject *str = PyObject_Str(failure->detail_obj);
+
+ if (str != NULL)
+ {
+ detail = PyString_FromFormat(
+ "%s keyword argument name is not a string",
+ PyString_AsString(str));
+
+ Py_DECREF(str);
+ }
+ else
+ {
+ detail = NULL;
+ }
+ }
+#endif
+ break;
+
+ case UnknownKeyword:
+#if PY_MAJOR_VERSION >= 3
+ detail = PyUnicode_FromFormat("'%U' is not a valid keyword argument",
+ failure->detail_obj);
+#else
+ detail = PyString_FromFormat("'%s' is not a valid keyword argument",
+ PyString_AS_STRING(failure->detail_obj));
+#endif
+ break;
+
+ case Duplicate:
+#if PY_MAJOR_VERSION >= 3
+ detail = PyUnicode_FromFormat(
+ "'%U' has already been given as a positional argument",
+ failure->detail_obj);
+#else
+ detail = PyString_FromFormat(
+ "'%s' has already been given as a positional argument",
+ PyString_AS_STRING(failure->detail_obj));
+#endif
+ break;
+
+ case WrongType:
+ if (failure->arg_nr >= 0)
+ {
+ detail = bad_type_str(failure->arg_nr, failure->detail_obj);
+ }
+ else
+ {
+#if PY_MAJOR_VERSION >= 3
+ detail = PyUnicode_FromFormat(
+ "keyword argument '%s' has unexpected type '%s'",
+ failure->arg_name, Py_TYPE(failure->detail_obj)->tp_name);
+#else
+ detail = PyString_FromFormat(
+ "keyword argument '%s' has unexpected type '%s'",
+ failure->arg_name, Py_TYPE(failure->detail_obj)->tp_name);
+#endif
+ }
+
+ break;
+
+ case Exception:
+ detail = failure->detail_obj;
+
+ if (detail)
+ {
+ Py_INCREF(detail);
+ break;
+ }
+
+ /* Drop through. */
+
+ default:
+#if PY_MAJOR_VERSION >= 3
+ detail = PyUnicode_FromString("unknown reason");
+#else
+ detail = PyString_FromString("unknown reason");
+#endif
+ }
+
+ return detail;
+}
+
+
+/*
+ * Report an abstract method called with an unbound self.
+ */
+static void sip_api_abstract_method(const char *classname, const char *method)
+{
+ PyErr_Format(PyExc_TypeError,
+ "%s.%s() is abstract and cannot be called as an unbound method",
+ classname, method);
+}
+
+
+/*
+ * Report a deprecated class or method.
+ */
+static int sip_api_deprecated(const char *classname, const char *method)
+{
+ char buf[100];
+
+ if (classname == NULL)
+ PyOS_snprintf(buf, sizeof (buf), "%s() is deprecated", method);
+ else if (method == NULL)
+ PyOS_snprintf(buf, sizeof (buf), "%s constructor is deprecated",
+ classname);
+ else
+ PyOS_snprintf(buf, sizeof (buf), "%s.%s() is deprecated", classname,
+ method);
+
+#if PY_VERSION_HEX >= 0x02050000
+ return PyErr_WarnEx(PyExc_DeprecationWarning, buf, 1);
+#else
+ return PyErr_Warn(PyExc_DeprecationWarning, buf);
+#endif
+}
+
+
+/*
+ * Report a bad operator argument. Only a small subset of operators need to
+ * be handled (those that don't return Py_NotImplemented).
+ */
+static void sip_api_bad_operator_arg(PyObject *self, PyObject *arg,
+ sipPySlotType st)
+{
+ const char *sn = NULL;
+
+ /* Try and get the text to match a Python exception. */
+
+ switch (st)
+ {
+ case concat_slot:
+ case iconcat_slot:
+ PyErr_Format(PyExc_TypeError,
+ "cannot concatenate '%s' and '%s' objects",
+ Py_TYPE(self)->tp_name, Py_TYPE(arg)->tp_name);
+ break;
+
+ case repeat_slot:
+ sn = "*";
+ break;
+
+ case irepeat_slot:
+ sn = "*=";
+ break;
+
+ default:
+ sn = "unknown";
+ }
+
+ if (sn != NULL)
+ PyErr_Format(PyExc_TypeError,
+ "unsupported operand type(s) for %s: '%s' and '%s'", sn,
+ Py_TYPE(self)->tp_name, Py_TYPE(arg)->tp_name);
+}
+
+
+/*
+ * Report a sequence length that does not match the length of a slice.
+ */
+static void sip_api_bad_length_for_slice(SIP_SSIZE_T seqlen,
+ SIP_SSIZE_T slicelen)
+{
+ PyErr_Format(PyExc_ValueError,
+#if PY_VERSION_HEX >= 0x02050000
+ "attempt to assign sequence of size %zd to slice of size %zd",
+#else
+ "attempt to assign sequence of size %d to slice of size %d",
+#endif
+ seqlen, slicelen);
+}
+
+
+/*
+ * Report a Python object that cannot be converted to a particular class.
+ */
+static void sip_api_bad_class(const char *classname)
+{
+ PyErr_Format(PyExc_TypeError,
+ "cannot convert Python object to an instance of %s", classname);
+}
+
+
+/*
+ * Report a Python member function with an unexpected return type.
+ */
+static void sip_api_bad_catcher_result(PyObject *method)
+{
+ PyObject *mname;
+
+ /*
+ * This is part of the public API so we make no assumptions about the
+ * method object.
+ */
+ if (!PyMethod_Check(method) ||
+ PyMethod_GET_FUNCTION(method) == NULL ||
+ !PyFunction_Check(PyMethod_GET_FUNCTION(method)) ||
+ PyMethod_GET_SELF(method) == NULL)
+ {
+ PyErr_Format(PyExc_TypeError,
+ "invalid argument to sipBadCatcherResult()");
+ return;
+ }
+
+ mname = ((PyFunctionObject *)PyMethod_GET_FUNCTION(method))->func_name;
+
+#if PY_MAJOR_VERSION >= 3
+ PyErr_Format(PyExc_TypeError, "invalid result type from %s.%U()",
+ Py_TYPE(PyMethod_GET_SELF(method))->tp_name, mname);
+#else
+ PyErr_Format(PyExc_TypeError, "invalid result type from %s.%s()",
+ Py_TYPE(PyMethod_GET_SELF(method))->tp_name,
+ PyString_AsString(mname));
+#endif
+}
+
+
+/*
+ * Transfer ownership of a class instance to Python from C/C++.
+ */
+static void sip_api_transfer_back(PyObject *self)
+{
+ if (self != NULL && PyObject_TypeCheck(self, (PyTypeObject *)&sipWrapper_Type))
+ {
+ sipSimpleWrapper *sw = (sipSimpleWrapper *)self;
+
+ if (sipCppHasRef(sw))
+ {
+ sipResetCppHasRef(sw);
+ Py_DECREF(sw);
+ }
+ else
+ removeFromParent((sipWrapper *)sw);
+
+ sipSetPyOwned(sw);
+ }
+}
+
+
+/*
+ * Break the association of a C++ owned Python object with any parent.
+ */
+static void sip_api_transfer_break(PyObject *self)
+{
+ if (self != NULL && PyObject_TypeCheck(self, (PyTypeObject *)&sipWrapper_Type))
+ {
+ sipSimpleWrapper *sw = (sipSimpleWrapper *)self;
+
+ if (sipCppHasRef(sw))
+ {
+ sipResetCppHasRef(sw);
+ Py_DECREF(sw);
+ }
+ else
+ removeFromParent((sipWrapper *)sw);
+ }
+}
+
+
+/*
+ * Transfer ownership of a class instance to C/C++ from Python.
+ */
+static void sip_api_transfer_to(PyObject *self, PyObject *owner)
+{
+ /*
+ * There is a legitimate case where we try to transfer a PyObject that
+ * may not be a SIP generated class. The virtual handler code calls
+ * this function to keep the C/C++ instance alive when it gets rid of
+ * the Python object returned by the Python method. A class may have
+ * handwritten code that converts a regular Python type - so we can't
+ * assume that we can simply cast to sipWrapper.
+ */
+ if (self != NULL &&
+ PyObject_TypeCheck(self, (PyTypeObject *)&sipWrapper_Type) &&
+ (owner == NULL ||
+ PyObject_TypeCheck(owner, (PyTypeObject *)&sipWrapper_Type)))
+ {
+ sipSimpleWrapper *sw = (sipSimpleWrapper *)self;
+
+ /*
+ * Keep the object alive while we do the transfer. If C++ has a
+ * reference then there is no need to increment it, just reset the flag
+ * and the following decrement will bring everything back to the way it
+ * should be.
+ */
+ if (sipCppHasRef(sw))
+ sipResetCppHasRef(sw);
+ else
+ {
+ Py_INCREF(sw);
+ removeFromParent((sipWrapper *)sw);
+ }
+
+ if (owner != NULL)
+ addToParent((sipWrapper *)sw, (sipWrapper *)owner);
+
+ Py_DECREF(sw);
+
+ sipResetPyOwned(sw);
+ }
+}
+
+
+/*
+ * Add a license to a dictionary.
+ */
+static int addLicense(PyObject *dict,sipLicenseDef *lc)
+{
+ int rc;
+ PyObject *ldict, *proxy, *o;
+
+ /* Convert the strings we use to objects if not already done. */
+
+ if (objectify("__license__", &licenseName) < 0)
+ return -1;
+
+ if (objectify("Licensee", &licenseeName) < 0)
+ return -1;
+
+ if (objectify("Type", &typeName) < 0)
+ return -1;
+
+ if (objectify("Timestamp", &timestampName) < 0)
+ return -1;
+
+ if (objectify("Signature", &signatureName) < 0)
+ return -1;
+
+ /* We use a dictionary to hold the license information. */
+ if ((ldict = PyDict_New()) == NULL)
+ return -1;
+
+ /* The license type is compulsory, the rest are optional. */
+ if (lc->lc_type == NULL)
+ goto deldict;
+
+#if PY_MAJOR_VERSION >= 3
+ o = PyUnicode_FromString(lc->lc_type);
+#else
+ o = PyString_FromString(lc->lc_type);
+#endif
+
+ if (o == NULL)
+ goto deldict;
+
+ rc = PyDict_SetItem(ldict,typeName,o);
+ Py_DECREF(o);
+
+ if (rc < 0)
+ goto deldict;
+
+ if (lc->lc_licensee != NULL)
+ {
+#if PY_MAJOR_VERSION >= 3
+ o = PyUnicode_FromString(lc->lc_licensee);
+#else
+ o = PyString_FromString(lc->lc_licensee);
+#endif
+
+ if (o == NULL)
+ goto deldict;
+
+ rc = PyDict_SetItem(ldict,licenseeName,o);
+ Py_DECREF(o);
+
+ if (rc < 0)
+ goto deldict;
+ }
+
+ if (lc->lc_timestamp != NULL)
+ {
+#if PY_MAJOR_VERSION >= 3
+ o = PyUnicode_FromString(lc->lc_timestamp);
+#else
+ o = PyString_FromString(lc->lc_timestamp);
+#endif
+
+ if (o == NULL)
+ goto deldict;
+
+ rc = PyDict_SetItem(ldict,timestampName,o);
+ Py_DECREF(o);
+
+ if (rc < 0)
+ goto deldict;
+ }
+
+ if (lc->lc_signature != NULL)
+ {
+#if PY_MAJOR_VERSION >= 3
+ o = PyUnicode_FromString(lc->lc_signature);
+#else
+ o = PyString_FromString(lc->lc_signature);
+#endif
+
+ if (o == NULL)
+ goto deldict;
+
+ rc = PyDict_SetItem(ldict,signatureName,o);
+ Py_DECREF(o);
+
+ if (rc < 0)
+ goto deldict;
+ }
+
+ /* Create a read-only proxy. */
+ if ((proxy = PyDictProxy_New(ldict)) == NULL)
+ goto deldict;
+
+ Py_DECREF(ldict);
+
+ rc = PyDict_SetItem(dict, licenseName, proxy);
+ Py_DECREF(proxy);
+
+ return rc;
+
+deldict:
+ Py_DECREF(ldict);
+
+ return -1;
+}
+
+
+/*
+ * Add the void pointer instances to a dictionary.
+ */
+static int addVoidPtrInstances(PyObject *dict,sipVoidPtrInstanceDef *vi)
+{
+ while (vi->vi_name != NULL)
+ {
+ int rc;
+ PyObject *w;
+
+ if ((w = sip_api_convert_from_void_ptr(vi->vi_val)) == NULL)
+ return -1;
+
+ rc = PyDict_SetItemString(dict,vi->vi_name,w);
+ Py_DECREF(w);
+
+ if (rc < 0)
+ return -1;
+
+ ++vi;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Add the char instances to a dictionary.
+ */
+static int addCharInstances(PyObject *dict, sipCharInstanceDef *ci)
+{
+ while (ci->ci_name != NULL)
+ {
+ int rc;
+ PyObject *w;
+
+ switch (ci->ci_encoding)
+ {
+ case 'A':
+ w = PyUnicode_DecodeASCII(&ci->ci_val, 1, NULL);
+ break;
+
+ case 'L':
+ w = PyUnicode_DecodeLatin1(&ci->ci_val, 1, NULL);
+ break;
+
+ case '8':
+#if PY_MAJOR_VERSION >= 3
+ w = PyUnicode_FromStringAndSize(&ci->ci_val, 1);
+#else
+ w = PyUnicode_DecodeUTF8(&ci->ci_val, 1, NULL);
+#endif
+ break;
+
+ default:
+ w = SIPBytes_FromStringAndSize(&ci->ci_val, 1);
+ }
+
+ if (w == NULL)
+ return -1;
+
+ rc = PyDict_SetItemString(dict, ci->ci_name, w);
+ Py_DECREF(w);
+
+ if (rc < 0)
+ return -1;
+
+ ++ci;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Add the string instances to a dictionary.
+ */
+static int addStringInstances(PyObject *dict, sipStringInstanceDef *si)
+{
+ while (si->si_name != NULL)
+ {
+ int rc;
+ PyObject *w;
+
+ switch (si->si_encoding)
+ {
+ case 'A':
+ w = PyUnicode_DecodeASCII(si->si_val, strlen(si->si_val), NULL);
+ break;
+
+ case 'L':
+ w = PyUnicode_DecodeLatin1(si->si_val, strlen(si->si_val), NULL);
+ break;
+
+ case '8':
+#if PY_MAJOR_VERSION >= 3
+ w = PyUnicode_FromString(si->si_val);
+#else
+ w = PyUnicode_DecodeUTF8(si->si_val, strlen(si->si_val), NULL);
+#endif
+ break;
+
+ default:
+ w = SIPBytes_FromString(si->si_val);
+ }
+
+ if (w == NULL)
+ return -1;
+
+ rc = PyDict_SetItemString(dict, si->si_name, w);
+ Py_DECREF(w);
+
+ if (rc < 0)
+ return -1;
+
+ ++si;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Add the int instances to a dictionary.
+ */
+static int addIntInstances(PyObject *dict, sipIntInstanceDef *ii)
+{
+ while (ii->ii_name != NULL)
+ {
+ int rc;
+ PyObject *w;
+
+#if PY_MAJOR_VERSION >= 3
+ w = PyLong_FromLong(ii->ii_val);
+#else
+ w = PyInt_FromLong(ii->ii_val);
+#endif
+
+ if (w == NULL)
+ return -1;
+
+ rc = PyDict_SetItemString(dict, ii->ii_name, w);
+ Py_DECREF(w);
+
+ if (rc < 0)
+ return -1;
+
+ ++ii;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Add the long instances to a dictionary.
+ */
+static int addLongInstances(PyObject *dict,sipLongInstanceDef *li)
+{
+ while (li->li_name != NULL)
+ {
+ int rc;
+ PyObject *w;
+
+ if ((w = PyLong_FromLong(li->li_val)) == NULL)
+ return -1;
+
+ rc = PyDict_SetItemString(dict,li->li_name,w);
+ Py_DECREF(w);
+
+ if (rc < 0)
+ return -1;
+
+ ++li;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Add the unsigned long instances to a dictionary.
+ */
+static int addUnsignedLongInstances(PyObject *dict, sipUnsignedLongInstanceDef *uli)
+{
+ while (uli->uli_name != NULL)
+ {
+ int rc;
+ PyObject *w;
+
+ if ((w = PyLong_FromUnsignedLong(uli->uli_val)) == NULL)
+ return -1;
+
+ rc = PyDict_SetItemString(dict, uli->uli_name, w);
+ Py_DECREF(w);
+
+ if (rc < 0)
+ return -1;
+
+ ++uli;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Add the long long instances to a dictionary.
+ */
+static int addLongLongInstances(PyObject *dict, sipLongLongInstanceDef *lli)
+{
+ while (lli->lli_name != NULL)
+ {
+ int rc;
+ PyObject *w;
+
+#if defined(HAVE_LONG_LONG)
+ if ((w = PyLong_FromLongLong(lli->lli_val)) == NULL)
+#else
+ if ((w = PyLong_FromLong(lli->lli_val)) == NULL)
+#endif
+ return -1;
+
+ rc = PyDict_SetItemString(dict, lli->lli_name, w);
+ Py_DECREF(w);
+
+ if (rc < 0)
+ return -1;
+
+ ++lli;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Add the unsigned long long instances to a dictionary.
+ */
+static int addUnsignedLongLongInstances(PyObject *dict, sipUnsignedLongLongInstanceDef *ulli)
+{
+ while (ulli->ulli_name != NULL)
+ {
+ int rc;
+ PyObject *w;
+
+#if defined(HAVE_LONG_LONG)
+ if ((w = PyLong_FromUnsignedLongLong(ulli->ulli_val)) == NULL)
+#else
+ if ((w = PyLong_FromUnsignedLong(ulli->ulli_val)) == NULL)
+#endif
+ return -1;
+
+ rc = PyDict_SetItemString(dict, ulli->ulli_name, w);
+ Py_DECREF(w);
+
+ if (rc < 0)
+ return -1;
+
+ ++ulli;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Add the double instances to a dictionary.
+ */
+static int addDoubleInstances(PyObject *dict,sipDoubleInstanceDef *di)
+{
+ while (di->di_name != NULL)
+ {
+ int rc;
+ PyObject *w;
+
+ if ((w = PyFloat_FromDouble(di->di_val)) == NULL)
+ return -1;
+
+ rc = PyDict_SetItemString(dict,di->di_name,w);
+ Py_DECREF(w);
+
+ if (rc < 0)
+ return -1;
+
+ ++di;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Wrap a set of type instances and add them to a dictionary.
+ */
+static int addTypeInstances(PyObject *dict, sipTypeInstanceDef *ti)
+{
+ while (ti->ti_name != NULL)
+ {
+ if (addSingleTypeInstance(dict, ti->ti_name, ti->ti_ptr, *ti->ti_type, ti->ti_flags) < 0)
+ return -1;
+
+ ++ti;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Wrap a single type instance and add it to a dictionary.
+ */
+static int addSingleTypeInstance(PyObject *dict, const char *name,
+ void *cppPtr, const sipTypeDef *td, int initflags)
+{
+ int rc;
+ PyObject *obj;
+
+ if (sipTypeIsClass(td))
+ {
+ obj = sipWrapSimpleInstance(cppPtr, td, NULL, initflags);
+ }
+ else if (sipTypeIsEnum(td))
+ {
+ obj = sip_api_convert_from_enum(*(int *)cppPtr, td);
+ }
+ else
+ {
+ assert(sipTypeIsMapped(td));
+
+ obj = ((const sipMappedTypeDef *)td)->mtd_cfrom(cppPtr, NULL);
+ }
+
+ if (obj == NULL)
+ return -1;
+
+ rc = PyDict_SetItemString(dict, name, obj);
+ Py_DECREF(obj);
+
+ return rc;
+}
+
+
+/*
+ * Convert a type instance and add it to a dictionary.
+ */
+static int sip_api_add_type_instance(PyObject *dict, const char *name,
+ void *cppPtr, const sipTypeDef *td)
+{
+ return addSingleTypeInstance(getDictFromObject(dict), name, cppPtr, td, 0);
+}
+
+
+/*
+ * Return the instance dictionary for an object if it is a wrapped type.
+ * Otherwise assume that it is a module dictionary.
+ */
+static PyObject *getDictFromObject(PyObject *obj)
+{
+ if (PyObject_TypeCheck(obj, (PyTypeObject *)&sipWrapperType_Type))
+ obj = ((PyTypeObject *)obj)->tp_dict;
+
+ return obj;
+}
+
+
+/*
+ * Return a Python reimplementation corresponding to a C/C++ virtual function,
+ * if any. If one was found then the Python lock is acquired.
+ */
+static PyObject *sip_api_is_py_method(sip_gilstate_t *gil, char *pymc,
+ sipSimpleWrapper *sipSelf, const char *cname, const char *mname)
+{
+ PyObject *mname_obj, *reimp, *mro, *cls;
+ SIP_SSIZE_T i;
+
+
+ /*
+ * This is the most common case (where there is no Python reimplementation)
+ * so we take a fast shortcut without acquiring the GIL.
+ */
+ if (*pymc != 0)
+ return NULL;
+
+ /* We might still have C++ going after the interpreter has gone. */
+ if (sipInterpreter == NULL)
+ return NULL;
+
+ /*
+ * It's possible that the Python object has been deleted but the underlying
+ * C++ instance is still working and trying to handle virtual functions.
+ * Alternatively, an instance has started handling virtual functions before
+ * its ctor has returned. In either case say there is no Python
+ * reimplementation.
+ */
+ if (sipSelf == NULL)
+ return NULL;
+
+ /* Get any reimplementation. */
+
+#ifdef WITH_THREAD
+ *gil = PyGILState_Ensure();
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+ mname_obj = PyUnicode_FromString(mname);
+#else
+ mname_obj = PyString_FromString(mname);
+#endif
+
+ if (mname_obj == NULL)
+ {
+#ifdef WITH_THREAD
+ PyGILState_Release(*gil);
+#endif
+ return NULL;
+ }
+
+ /*
+ * We don't use PyObject_GetAttr() because that might find the generated
+ * C function before a reimplementation defined in a mixin (ie. later in
+ * the MRO).
+ */
+
+ if (sipSelf->dict != NULL)
+ {
+ /* Check the instance dictionary in case it has been monkey patched. */
+ if ((reimp = PyDict_GetItem(sipSelf->dict, mname_obj)) != NULL && PyCallable_Check(reimp))
+ {
+ Py_DECREF(mname_obj);
+
+ Py_INCREF(reimp);
+ return reimp;
+ }
+ }
+
+ cls = (PyObject *)Py_TYPE(sipSelf);
+ mro = ((PyTypeObject *)cls)->tp_mro;
+ assert(PyTuple_Check(mro));
+
+ reimp = NULL;
+
+ for (i = 0; i < PyTuple_GET_SIZE(mro); ++i)
+ {
+ PyObject *cls_dict;
+
+ cls = PyTuple_GET_ITEM(mro, i);
+
+#if PY_MAJOR_VERSION >= 3
+ cls_dict = ((PyTypeObject *)cls)->tp_dict;
+#else
+ // Allow for classic classes as mixins.
+ if (PyClass_Check(cls))
+ cls_dict = ((PyClassObject *)cls)->cl_dict;
+ else
+ cls_dict = ((PyTypeObject *)cls)->tp_dict;
+#endif
+
+ if (cls_dict != NULL && (reimp = PyDict_GetItem(cls_dict, mname_obj)) != NULL)
+ {
+ /*
+ * Check any reimplementation is Python code and is not the wrapped
+ * C++ method.
+ */
+ if (PyMethod_Check(reimp))
+ {
+ /* It's already a method but make sure it is bound. */
+ if (PyMethod_GET_SELF(reimp) != NULL)
+ {
+ Py_INCREF(reimp);
+ }
+ else
+ {
+#if PY_MAJOR_VERSION >= 3
+ reimp = PyMethod_New(PyMethod_GET_FUNCTION(reimp),
+ (PyObject *)sipSelf);
+#else
+ reimp = PyMethod_New(PyMethod_GET_FUNCTION(reimp),
+ (PyObject *)sipSelf, PyMethod_GET_CLASS(reimp));
+#endif
+ }
+
+ break;
+ }
+
+ if (PyFunction_Check(reimp))
+ {
+#if PY_MAJOR_VERSION >= 3
+ reimp = PyMethod_New(reimp, (PyObject *)sipSelf);
+#else
+ reimp = PyMethod_New(reimp, (PyObject *)sipSelf, cls);
+#endif
+
+ break;
+ }
+
+ reimp = NULL;
+ }
+ }
+
+ Py_DECREF(mname_obj);
+
+ if (reimp == NULL)
+ {
+ /* Use the fast track in future. */
+ *pymc = 1;
+
+ if (cname != NULL)
+ {
+ /* Note that this will only be raised once per method. */
+ PyErr_Format(PyExc_NotImplementedError,
+ "%s.%s() is abstract and must be overridden", cname,
+ mname);
+ PyErr_Print();
+ }
+
+#ifdef WITH_THREAD
+ PyGILState_Release(*gil);
+#endif
+ }
+
+ return reimp;
+}
+
+
+/*
+ * Convert a C/C++ pointer to the object that wraps it.
+ */
+static PyObject *sip_api_get_pyobject(void *cppPtr, const sipTypeDef *td)
+{
+ return (PyObject *)sipOMFindObject(&cppPyMap, cppPtr, td);
+}
+
+
+/*
+ * Return the C/C++ pointer from a wrapper without any checks.
+ */
+void *sipGetAddress(sipSimpleWrapper *sw)
+{
+ if (sipIsAccessFunc(sw))
+ return (*sw->u.afPtr)();
+
+ if (sipIsIndirect(sw))
+ return *((void **)sw->u.cppPtr);
+
+ return sw->u.cppPtr;
+}
+
+
+/*
+ * Get the C/C++ pointer for a complex object. Note that not casting the C++
+ * pointer is a bug. However this is only ever called by PyQt3 signal emitter
+ * code and PyQt doesn't contain anything that multiply inherits from QObject.
+ */
+static void *sip_api_get_complex_cpp_ptr(sipSimpleWrapper *sw)
+{
+ return getComplexCppPtr(sw, NULL);
+}
+
+
+/*
+ * Get the C/C++ pointer for a complex object and optionally cast it to the
+ * required type.
+ */
+static void *getComplexCppPtr(sipSimpleWrapper *sw, const sipTypeDef *td)
+{
+ if (!sipIsDerived(sw))
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "no access to protected functions or signals for objects not created from Python");
+
+ return NULL;
+ }
+
+ return sip_api_get_cpp_ptr(sw, td);
+}
+
+
+/*
+ * Get the C/C++ pointer from a wrapper and optionally cast it to the required
+ * type.
+ */
+void *sip_api_get_cpp_ptr(sipSimpleWrapper *sw, const sipTypeDef *td)
+{
+ void *ptr = sipGetAddress(sw);
+
+ if (checkPointer(ptr) < 0)
+ return NULL;
+
+ if (td != NULL)
+ {
+ ptr = cast_cpp_ptr(ptr, Py_TYPE(sw), td);
+
+ if (ptr == NULL)
+ PyErr_Format(PyExc_TypeError, "could not convert '%s' to '%s'",
+ Py_TYPE(sw)->tp_name,
+ sipPyNameOfContainer(&((const sipClassTypeDef *)td)->ctd_container, td));
+ }
+
+ return ptr;
+}
+
+
+/*
+ * Cast a C/C++ pointer from a source type to a destination type.
+ */
+static void *cast_cpp_ptr(void *ptr, PyTypeObject *src_type,
+ const sipTypeDef *dst_type)
+{
+ sipCastFunc cast = ((const sipClassTypeDef *)((sipWrapperType *)src_type)->type)->ctd_cast;
+
+ /* C structures don't have cast functions. */
+ if (cast != NULL)
+ ptr = (*cast)(ptr, dst_type);
+
+ return ptr;
+}
+
+
+/*
+ * Check that a pointer is non-NULL.
+ */
+static int checkPointer(void *ptr)
+{
+ if (ptr == NULL)
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "underlying C/C++ object has been deleted");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Keep an extra reference to an object.
+ */
+static void sip_api_keep_reference(PyObject *self, int key, PyObject *obj)
+{
+ PyObject *dict, *key_obj;
+
+ /*
+ * If there isn't a "self" to keep the extra reference for later garbage
+ * collection then just take a reference and let it leak. This could
+ * happen, for example, if virtuals were still being called while Python
+ * was shutting down.
+ */
+ if (self == NULL)
+ {
+ Py_XINCREF(obj);
+ return;
+ }
+
+ /* Create the extra references dictionary if needed. */
+ if ((dict = ((sipSimpleWrapper *)self)->extra_refs) == NULL)
+ {
+ if ((dict = PyDict_New()) == NULL)
+ return;
+
+ ((sipSimpleWrapper *)self)->extra_refs = dict;
+ }
+
+#if PY_MAJOR_VERSION >= 3
+ key_obj = PyLong_FromLong(key);
+#else
+ key_obj = PyInt_FromLong(key);
+#endif
+
+ if (key_obj != NULL)
+ {
+ /* This can happen if the argument was optional. */
+ if (obj == NULL)
+ obj = Py_None;
+
+ PyDict_SetItem(dict, key_obj, obj);
+ Py_DECREF(key_obj);
+ }
+}
+
+
+/*
+ * Check to see if a Python object can be converted to a type.
+ */
+static int sip_api_can_convert_to_type(PyObject *pyObj, const sipTypeDef *td,
+ int flags)
+{
+ int ok;
+
+ assert(sipTypeIsClass(td) || sipTypeIsMapped(td));
+
+ /* None is handled outside the type checkers. */
+ if (pyObj == Py_None)
+ {
+ /* If the type explicitly handles None then ignore the flags. */
+ if (sipTypeAllowNone(td))
+ ok = TRUE;
+ else
+ ok = ((flags & SIP_NOT_NONE) == 0);
+ }
+ else
+ {
+ sipConvertToFunc cto;
+
+ if (sipTypeIsClass(td))
+ {
+ cto = ((const sipClassTypeDef *)td)->ctd_cto;
+
+ if (cto == NULL || (flags & SIP_NO_CONVERTORS) != 0)
+ ok = PyObject_TypeCheck(pyObj, sipTypeAsPyTypeObject(td));
+ else
+ ok = cto(pyObj, NULL, NULL, NULL);
+ }
+ else
+ {
+ cto = ((const sipMappedTypeDef *)td)->mtd_cto;
+ ok = cto(pyObj, NULL, NULL, NULL);
+ }
+ }
+
+ return ok;
+}
+
+
+/*
+ * Convert a Python object to a C/C++ pointer, assuming a previous call to
+ * sip_api_can_convert_to_type() has been successful. Allow ownership to be
+ * transferred and any type convertors to be disabled.
+ */
+static void *sip_api_convert_to_type(PyObject *pyObj, const sipTypeDef *td,
+ PyObject *transferObj, int flags, int *statep, int *iserrp)
+{
+ void *cpp = NULL;
+ int state = 0;
+
+ assert(sipTypeIsClass(td) || sipTypeIsMapped(td));
+
+ /* Don't convert if there has already been an error. */
+ if (!*iserrp)
+ {
+ /* Do the conversion. */
+ if (pyObj == Py_None && !sipTypeAllowNone(td))
+ cpp = NULL;
+ else
+ {
+ sipConvertToFunc cto;
+
+ if (sipTypeIsClass(td))
+ {
+ cto = ((const sipClassTypeDef *)td)->ctd_cto;
+
+ if (cto == NULL || (flags & SIP_NO_CONVERTORS) != 0)
+ {
+ if ((cpp = sip_api_get_cpp_ptr((sipSimpleWrapper *)pyObj, td)) == NULL)
+ *iserrp = TRUE;
+ else if (transferObj != NULL)
+ {
+ if (transferObj == Py_None)
+ sip_api_transfer_back(pyObj);
+ else
+ sip_api_transfer_to(pyObj, transferObj);
+ }
+ }
+ else
+ {
+ state = cto(pyObj, &cpp, iserrp, transferObj);
+ }
+ }
+ else
+ {
+ cto = ((const sipMappedTypeDef *)td)->mtd_cto;
+ state = cto(pyObj, &cpp, iserrp, transferObj);
+ }
+ }
+ }
+
+ if (statep != NULL)
+ *statep = state;
+
+ return cpp;
+}
+
+
+/*
+ * Convert a Python object to a C/C++ pointer and raise an exception if it
+ * can't be done.
+ */
+static void *sip_api_force_convert_to_type(PyObject *pyObj,
+ const sipTypeDef *td, PyObject *transferObj, int flags, int *statep,
+ int *iserrp)
+{
+ /* Don't even try if there has already been an error. */
+ if (*iserrp)
+ return NULL;
+
+ /* See if the object's type can be converted. */
+ if (!sip_api_can_convert_to_type(pyObj, td, flags))
+ {
+ if (sipTypeIsMapped(td))
+ PyErr_Format(PyExc_TypeError,
+ "%s cannot be converted to a C/C++ %s in this context",
+ Py_TYPE(pyObj)->tp_name, sipTypeName(td));
+ else
+ PyErr_Format(PyExc_TypeError,
+ "%s cannot be converted to %s.%s in this context",
+ Py_TYPE(pyObj)->tp_name, sipNameOfModule(td->td_module),
+ sipPyNameOfContainer(&((const sipClassTypeDef *)td)->ctd_container, td));
+
+ if (statep != NULL)
+ *statep = 0;
+
+ *iserrp = TRUE;
+ return NULL;
+ }
+
+ /* Do the conversion. */
+ return sip_api_convert_to_type(pyObj, td, transferObj, flags, statep,
+ iserrp);
+}
+
+
+/*
+ * Release a possibly temporary C/C++ instance created by a type convertor.
+ */
+static void sip_api_release_type(void *cpp, const sipTypeDef *td, int state)
+{
+ /* See if there is something to release. */
+ if (state & SIP_TEMPORARY)
+ release(cpp, td, state);
+}
+
+
+/*
+ * Release an instance.
+ */
+static void release(void *addr, const sipTypeDef *td, int state)
+{
+ sipReleaseFunc rel;
+
+ if (sipTypeIsClass(td))
+ {
+ rel = ((const sipClassTypeDef *)td)->ctd_release;
+
+ /*
+ * If there is no release function then it must be a C structure and we
+ * can just free it.
+ */
+ if (rel == NULL)
+ sip_api_free(addr);
+ }
+ else if (sipTypeIsMapped(td))
+ rel = ((const sipMappedTypeDef *)td)->mtd_release;
+ else
+ rel = NULL;
+
+ if (rel != NULL)
+ rel(addr, state);
+}
+
+
+/*
+ * Convert a C/C++ instance to a Python instance.
+ */
+PyObject *sip_api_convert_from_type(void *cpp, const sipTypeDef *td,
+ PyObject *transferObj)
+{
+ PyObject *py;
+
+ assert(sipTypeIsClass(td) || sipTypeIsMapped(td));
+
+ /* Handle None. */
+ if (cpp == NULL)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ if (sipTypeIsMapped(td))
+ return ((const sipMappedTypeDef *)td)->mtd_cfrom(cpp, transferObj);
+
+ /* Apply any sub-class convertor. */
+ if (sipTypeHasSCC(td))
+ td = convertSubClass(td, &cpp);
+
+ /* See if we have already wrapped it. */
+ if ((py = sip_api_get_pyobject(cpp, td)) != NULL)
+ Py_INCREF(py);
+ else if ((py = sipWrapSimpleInstance(cpp, td, NULL, SIP_SHARE_MAP)) == NULL)
+ return NULL;
+
+ /* Handle any ownership transfer. */
+ if (transferObj != NULL)
+ {
+ if (transferObj == Py_None)
+ sip_api_transfer_back(py);
+ else
+ sip_api_transfer_to(py, transferObj);
+ }
+
+ return py;
+}
+
+
+/*
+ * Convert a new C/C++ instance to a Python instance.
+ */
+static PyObject *sip_api_convert_from_new_type(void *cpp, const sipTypeDef *td,
+ PyObject *transferObj)
+{
+ sipWrapper *owner;
+
+ /* Handle None. */
+ if (cpp == NULL)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ if (sipTypeIsMapped(td))
+ {
+ PyObject *res = ((const sipMappedTypeDef *)td)->mtd_cfrom(cpp,
+ transferObj);
+
+ if (res != NULL)
+ {
+ /*
+ * We no longer need the C/C++ instance so we release it (unless
+ * its ownership is transferred). This means this call is
+ * semantically equivalent to the case where the type is a wrapped
+ * class.
+ */
+ if (transferObj == NULL || transferObj == Py_None)
+ release(cpp, td, 0);
+ }
+
+ return res;
+ }
+
+ assert(sipTypeIsClass(td));
+
+ /* Apply any sub-class convertor. */
+ if (sipTypeHasSCC(td))
+ td = convertSubClass(td, &cpp);
+
+ /* Handle any ownership transfer. */
+ if (transferObj == NULL || transferObj == Py_None)
+ owner = NULL;
+ else
+ owner = (sipWrapper *)transferObj;
+
+ return sipWrapSimpleInstance(cpp, td, owner, (owner == NULL ? SIP_PY_OWNED : 0));
+}
+
+
+/*
+ * Implement the normal transfer policy for the result of %ConvertToTypeCode,
+ * ie. it is temporary unless it is being transferred from Python.
+ */
+int sip_api_get_state(PyObject *transferObj)
+{
+ return (transferObj == NULL || transferObj == Py_None) ? SIP_TEMPORARY : 0;
+}
+
+
+/*
+ * This is set by sip_api_find_type() before calling bsearch() on the types
+ * table for the module. This is a hack that works around the problem of
+ * unresolved externally defined types.
+ */
+static sipExportedModuleDef *module_searched;
+
+
+/*
+ * The bsearch() helper function for searching the types table.
+ */
+static int compareTypeDef(const void *key, const void *el)
+{
+ const char *s1 = (const char *)key;
+ const char *s2 = NULL;
+ const sipTypeDef *td;
+ char ch1, ch2;
+
+ /* Allow for unresolved externally defined types. */
+ td = *(const sipTypeDef **)el;
+
+ if (td != NULL)
+ s2 = sipTypeName(td);
+ else
+ {
+ sipExternalTypeDef *etd = module_searched->em_external;
+
+ assert(etd != NULL);
+
+ /* Find which external type it is. */
+ while (etd->et_nr >= 0)
+ {
+ const sipTypeDef **tdp = &module_searched->em_types[etd->et_nr];
+
+ if (tdp == (const sipTypeDef **)el)
+ {
+ s2 = etd->et_name;
+ break;
+ }
+
+ ++etd;
+ }
+
+ assert(s2 != NULL);
+ }
+
+ /*
+ * Compare while ignoring spaces so that we don't impose a rigorous naming
+ * standard. This only really affects template-based mapped types.
+ */
+ do
+ {
+ while ((ch1 = *s1++) == ' ')
+ ;
+
+ while ((ch2 = *s2++) == ' ')
+ ;
+
+ /* We might be looking for a pointer or a reference. */
+ if ((ch1 == '*' || ch1 == '&' || ch1 == '\0') && ch2 == '\0')
+ return 0;
+ }
+ while (ch1 == ch2);
+
+ return (ch1 < ch2 ? -1 : 1);
+}
+
+
+/*
+ * Return the type structure for a particular type.
+ */
+static const sipTypeDef *sip_api_find_type(const char *type)
+{
+ sipExportedModuleDef *em;
+
+ for (em = moduleList; em != NULL; em = em->em_next)
+ {
+ sipTypeDef **tdp;
+
+ /* The backdoor to the comparison helper. */
+ module_searched = em;
+
+ tdp = (sipTypeDef **)bsearch((const void *)type,
+ (const void *)em->em_types, em->em_nrtypes,
+ sizeof (sipTypeDef *), compareTypeDef);
+
+ if (tdp != NULL)
+ {
+ /*
+ * Note that this will be NULL for unresolved externally defined
+ * types.
+ */
+ return *tdp;
+ }
+ }
+
+ return NULL;
+}
+
+
+/*
+ * Return the mapped type structure for a particular mapped type. This is
+ * deprecated.
+ */
+static const sipMappedType *sip_api_find_mapped_type(const char *type)
+{
+ const sipTypeDef *td = sip_api_find_type(type);
+
+ if (td != NULL && sipTypeIsMapped(td))
+ return (const sipMappedType *)td;
+
+ return NULL;
+}
+
+
+/*
+ * Return the type structure for a particular class. This is deprecated.
+ */
+static sipWrapperType *sip_api_find_class(const char *type)
+{
+ const sipTypeDef *td = sip_api_find_type(type);
+
+ if (td != NULL && sipTypeIsClass(td))
+ return (sipWrapperType *)sipTypeAsPyTypeObject(td);
+
+ return NULL;
+}
+
+
+/*
+ * Return the type structure for a particular named enum. This is deprecated.
+ */
+static PyTypeObject *sip_api_find_named_enum(const char *type)
+{
+ const sipTypeDef *td = sip_api_find_type(type);
+
+ if (td != NULL && sipTypeIsEnum(td))
+ return sipTypeAsPyTypeObject(td);
+
+ return NULL;
+}
+
+
+/*
+ * Save the components of a Python method.
+ */
+void sipSaveMethod(sipPyMethod *pm, PyObject *meth)
+{
+ pm->mfunc = PyMethod_GET_FUNCTION(meth);
+ pm->mself = PyMethod_GET_SELF(meth);
+#if PY_MAJOR_VERSION < 3
+ pm->mclass = PyMethod_GET_CLASS(meth);
+#endif
+}
+
+
+/*
+ * Call a hook.
+ */
+static void sip_api_call_hook(const char *hookname)
+{
+ PyObject *dictofmods, *mod, *dict, *hook, *res;
+
+ /* Get the dictionary of modules. */
+ if ((dictofmods = PyImport_GetModuleDict()) == NULL)
+ return;
+
+ /* Get the __builtin__ module. */
+ if ((mod = PyDict_GetItemString(dictofmods, "__builtin__")) == NULL)
+ return;
+
+ /* Get it's dictionary. */
+ if ((dict = PyModule_GetDict(mod)) == NULL)
+ return;
+
+ /* Get the function hook. */
+ if ((hook = PyDict_GetItemString(dict, hookname)) == NULL)
+ return;
+
+ /* Call the hook and discard any result. */
+ res = PyObject_CallObject(hook, NULL);
+
+ Py_XDECREF(res);
+}
+
+
+/*
+ * Call any sub-class convertors for a given type returning a pointer to the
+ * sub-type object, and possibly modifying the C++ address (in the case of
+ * multiple inheritence).
+ */
+static const sipTypeDef *convertSubClass(const sipTypeDef *td, void **cppPtr)
+{
+ PyTypeObject *py_type = sipTypeAsPyTypeObject(td);
+ sipExportedModuleDef *em;
+
+ if (*cppPtr == NULL)
+ return NULL;
+
+ /*
+ * Note that this code depends on the fact that a module appears in the
+ * list of modules before any module it imports, ie. sub-class convertors
+ * will be invoked for more specific types first.
+ */
+ for (em = moduleList; em != NULL; em = em->em_next)
+ {
+ sipSubClassConvertorDef *scc;
+
+ if ((scc = em->em_convertors) == NULL)
+ continue;
+
+ while (scc->scc_convertor != NULL)
+ {
+ /*
+ * The base type is the "root" class that may have a number of
+ * convertors each handling a "branch" of the derived tree of
+ * classes. The "root" normally implements the base function that
+ * provides the RTTI used by the convertors and is re-implemented
+ * by derived classes. We therefore see if the target type is a
+ * sub-class of the root, ie. see if the convertor might be able to
+ * convert the target type to something more specific.
+ */
+ if (PyType_IsSubtype(py_type, sipTypeAsPyTypeObject(scc->scc_basetype)))
+ {
+ void *ptr;
+ const sipTypeDef *subtype;
+
+ ptr = cast_cpp_ptr(*cppPtr, py_type, scc->scc_basetype);
+ subtype = (*scc->scc_convertor)(&ptr);
+
+ /*
+ * We are only interested in types that are not super-classes
+ * of the target. This happens either because it is in an
+ * earlier convertor than the one that handles the type or it
+ * is in a later convertor that handles a different branch of
+ * the hierarchy. Either way, the ordering of the modules
+ * ensures that there will be no more than one and that it will
+ * be the right one.
+ */
+ if (subtype != NULL && !PyType_IsSubtype(py_type, sipTypeAsPyTypeObject(subtype)))
+ {
+ *cppPtr = ptr;
+ return subtype;
+ }
+ }
+
+ ++scc;
+ }
+ }
+
+ /*
+ * We haven't found the exact type, so return the most specific type that
+ * it must be. This can happen legitimately if the wrapped library is
+ * returning an internal class that is down-cast to a more generic class.
+ * Also we want this function to be safe when a class doesn't have any
+ * convertors.
+ */
+ return td;
+}
+
+
+/*
+ * The bsearch() helper function for searching a sorted string map table.
+ */
+static int compareStringMapEntry(const void *key,const void *el)
+{
+ return strcmp((const char *)key,((const sipStringTypeClassMap *)el)->typeString);
+}
+
+
+/*
+ * A convenience function for %ConvertToSubClassCode for types represented as a
+ * string. Returns the Python class object or NULL if the type wasn't
+ * recognised. This is deprecated.
+ */
+static sipWrapperType *sip_api_map_string_to_class(const char *typeString,
+ const sipStringTypeClassMap *map, int maplen)
+{
+ sipStringTypeClassMap *me;
+
+ me = (sipStringTypeClassMap *)bsearch((const void *)typeString,
+ (const void *)map,maplen,
+ sizeof (sipStringTypeClassMap),
+ compareStringMapEntry);
+
+ return ((me != NULL) ? *me->pyType : NULL);
+}
+
+
+/*
+ * The bsearch() helper function for searching a sorted integer map table.
+ */
+static int compareIntMapEntry(const void *keyp,const void *el)
+{
+ int key = *(int *)keyp;
+
+ if (key > ((const sipIntTypeClassMap *)el)->typeInt)
+ return 1;
+
+ if (key < ((const sipIntTypeClassMap *)el)->typeInt)
+ return -1;
+
+ return 0;
+}
+
+
+/*
+ * A convenience function for %ConvertToSubClassCode for types represented as
+ * an integer. Returns the Python class object or NULL if the type wasn't
+ * recognised. This is deprecated.
+ */
+static sipWrapperType *sip_api_map_int_to_class(int typeInt,
+ const sipIntTypeClassMap *map, int maplen)
+{
+ sipIntTypeClassMap *me;
+
+ me = (sipIntTypeClassMap *)bsearch((const void *)&typeInt,
+ (const void *)map,maplen,
+ sizeof (sipIntTypeClassMap),
+ compareIntMapEntry);
+
+ return ((me != NULL) ? *me->pyType : NULL);
+}
+
+
+/*
+ * Raise an unknown exception. Make no assumptions about the GIL.
+ */
+static void sip_api_raise_unknown_exception(void)
+{
+ static PyObject *mobj = NULL;
+
+ SIP_BLOCK_THREADS
+
+ objectify("unknown", &mobj);
+
+ PyErr_SetObject(PyExc_Exception, mobj);
+
+ SIP_UNBLOCK_THREADS
+}
+
+
+/*
+ * Raise an exception implemented as a type. Make no assumptions about the
+ * GIL.
+ */
+static void sip_api_raise_type_exception(const sipTypeDef *td, void *ptr)
+{
+ PyObject *self;
+
+ assert(sipTypeIsClass(td));
+
+ SIP_BLOCK_THREADS
+
+ self = sipWrapSimpleInstance(ptr, td, NULL, SIP_PY_OWNED);
+
+ PyErr_SetObject((PyObject *)sipTypeAsPyTypeObject(td), self);
+
+ Py_XDECREF(self);
+
+ SIP_UNBLOCK_THREADS
+}
+
+
+/*
+ * Return the module of an encoded type.
+ */
+static sipExportedModuleDef *getTypeModule(const sipEncodedTypeDef *enc,
+ sipExportedModuleDef *em)
+{
+ if (enc->sc_module != 255)
+ em = em->em_imports[enc->sc_module].im_module;
+
+ return em;
+}
+
+
+/*
+ * Return the generated type structure of an encoded type.
+ */
+static sipTypeDef *getGeneratedType(const sipEncodedTypeDef *enc,
+ sipExportedModuleDef *em)
+{
+ return getTypeModule(enc, em)->em_types[enc->sc_type];
+}
+
+
+/*
+ * Find a particular slot function for a type.
+ */
+static void *findSlot(PyObject *self, sipPySlotType st)
+{
+ void *slot;
+ PyTypeObject *py_type = Py_TYPE(self);
+
+ /* See if it is a wrapper. */
+ if (PyObject_TypeCheck((PyObject *)py_type, &sipWrapperType_Type))
+ {
+ sipClassTypeDef *ctd;
+
+ ctd = (sipClassTypeDef *)((sipWrapperType *)(py_type))->type;
+
+ if (ctd->ctd_pyslots != NULL)
+ slot = findSlotInType(ctd->ctd_pyslots, st);
+ else
+ slot = NULL;
+
+ if (slot == NULL)
+ {
+ sipEncodedTypeDef *sup;
+
+ /* Search any super-types. */
+ if ((sup = ctd->ctd_supers) != NULL)
+ {
+ sipClassTypeDef *sup_ctd;
+
+ do
+ {
+ sup_ctd = (sipClassTypeDef *)getGeneratedType(sup,
+ ctd->ctd_base.td_module);
+
+ if (sup_ctd->ctd_pyslots != NULL)
+ slot = findSlotInType(sup_ctd->ctd_pyslots, st);
+ }
+ while (slot == NULL && !sup++->sc_flag);
+ }
+ }
+ }
+ else
+ {
+ sipEnumTypeDef *etd;
+
+ /* If it is not a wrapper then it must be an enum. */
+ assert(PyObject_TypeCheck((PyObject *)py_type, &sipEnumType_Type));
+
+ etd = (sipEnumTypeDef *)((sipEnumTypeObject *)(py_type))->type;
+
+ assert(etd->etd_pyslots != NULL);
+
+ slot = findSlotInType(etd->etd_pyslots, st);
+ }
+
+ return slot;
+}
+
+
+/*
+ * Find a particular slot function in a particular type.
+ */
+static void *findSlotInType(sipPySlotDef *psd, sipPySlotType st)
+{
+ while (psd->psd_func != NULL)
+ {
+ if (psd->psd_type == st)
+ return psd->psd_func;
+
+ ++psd;
+ }
+
+ return NULL;
+}
+
+
+/*
+ * Return the C/C++ address and the generated class structure for a wrapper.
+ */
+static void *getPtrTypeDef(sipSimpleWrapper *self, const sipClassTypeDef **ctd)
+{
+ *ctd = (const sipClassTypeDef *)((sipWrapperType *)Py_TYPE(self))->type;
+
+ return (sipNotInMap(self) ? NULL : self->u.cppPtr);
+}
+
+
+/*
+ * Handle an objobjargproc slot.
+ */
+static int objobjargprocSlot(PyObject *self, PyObject *arg1, PyObject *arg2,
+ sipPySlotType st)
+{
+ int (*f)(PyObject *, PyObject *);
+ int res;
+
+ f = (int (*)(PyObject *, PyObject *))findSlot(self, st);
+
+ if (f != NULL)
+ {
+ PyObject *args;
+
+ /*
+ * Slot handlers require a single PyObject *. The second argument is
+ * optional.
+ */
+ if (arg2 == NULL)
+ {
+ args = arg1;
+ Py_INCREF(args);
+ }
+ else
+ {
+#if PY_VERSION_HEX >= 0x02040000
+ args = PyTuple_Pack(2, arg1, arg2);
+#else
+ args = Py_BuildValue("(OO)", arg1, arg2);
+#endif
+
+ if (args == NULL)
+ return -1;
+ }
+
+ res = f(self, args);
+ Py_DECREF(args);
+ }
+ else
+ {
+ PyErr_SetNone(PyExc_NotImplementedError);
+ res = -1;
+ }
+
+ return res;
+}
+
+
+/*
+ * Handle an ssizeobjargproc slot.
+ */
+static int ssizeobjargprocSlot(PyObject *self, SIP_SSIZE_T arg1,
+ PyObject *arg2, sipPySlotType st)
+{
+ int (*f)(PyObject *, PyObject *);
+ int res;
+
+ f = (int (*)(PyObject *, PyObject *))findSlot(self, st);
+
+ if (f != NULL)
+ {
+ PyObject *args;
+
+ /*
+ * Slot handlers require a single PyObject *. The second argument is
+ * optional.
+ */
+ if (arg2 == NULL)
+#if PY_MAJOR_VERSION >= 3
+ args = PyLong_FromSsize_t(arg1);
+#elif PY_VERSION_HEX >= 0x02050000
+ args = PyInt_FromSsize_t(arg1);
+#else
+ args = PyInt_FromLong(arg1);
+#endif
+ else
+#if PY_VERSION_HEX >= 0x02050000
+ args = Py_BuildValue("(nO)", arg1, arg2);
+#else
+ args = Py_BuildValue("(iO)", arg1, arg2);
+#endif
+
+ if (args == NULL)
+ return -1;
+
+ res = f(self, args);
+ Py_DECREF(args);
+ }
+ else
+ {
+ PyErr_SetNone(PyExc_NotImplementedError);
+ res = -1;
+ }
+
+ return res;
+}
+
+
+/*
+ * The metatype alloc slot.
+ */
+static PyObject *sipWrapperType_alloc(PyTypeObject *self, SIP_SSIZE_T nitems)
+{
+ PyObject *o;
+
+ /* Call the standard super-metatype alloc. */
+ if ((o = PyType_Type.tp_alloc(self, nitems)) == NULL)
+ return NULL;
+
+ /*
+ * Consume any extra type specific information and use it to initialise the
+ * slots. This only happens for directly wrapped classes (and not
+ * programmer written sub-classes). This must be done in the alloc
+ * function because it is the only place we can break out of the default
+ * new() function before PyType_Ready() is called.
+ */
+ if (currentType != NULL)
+ {
+ ((sipWrapperType *)o)->type = currentType;
+
+ if (sipTypeIsClass(currentType))
+ {
+ const char *docstring = ((sipClassTypeDef *)currentType)->ctd_docstring;
+
+ /*
+ * Skip the marker that identifies the docstring as being
+ * automatically generated.
+ */
+ if (docstring != NULL && *docstring == AUTO_DOCSTRING)
+ ++docstring;
+
+ ((PyTypeObject *)o)->tp_doc = docstring;
+
+ addClassSlots((sipWrapperType *)o, (sipClassTypeDef *)currentType);
+ }
+
+ currentType = NULL;
+ }
+
+ return o;
+}
+
+
+/*
+ * The metatype init slot.
+ */
+static int sipWrapperType_init(sipWrapperType *self, PyObject *args,
+ PyObject *kwds)
+{
+ /* Call the standard super-metatype init. */
+ if (PyType_Type.tp_init((PyObject *)self, args, kwds) < 0)
+ return -1;
+
+ /*
+ * If we don't yet have any extra type specific information (because we are
+ * a programmer defined sub-class) then get it from the (first) super-type.
+ */
+ if (self->type == NULL)
+ {
+ PyTypeObject *base = ((PyTypeObject *)self)->tp_base;
+
+ /*
+ * We allow the class to use this as a meta-type without being derived
+ * from a class that uses it. This allows mixin classes that need
+ * their own meta-type to work so long as their meta-type is derived
+ * from this meta-type. This condition is indicated by the pointer to
+ * the generated type structure being NULL.
+ */
+ if (base != NULL && PyObject_TypeCheck((PyObject *)base, (PyTypeObject *)&sipWrapperType_Type))
+ self->type = ((sipWrapperType *)base)->type;
+ }
+ else
+ {
+ /*
+ * We must be a generated type so remember the type object in the
+ * generated type structure.
+ */
+ assert(self->type->u.td_py_type == NULL);
+
+ self->type->u.td_py_type = (PyTypeObject *)self;
+ }
+
+ return 0;
+}
+
+
+/*
+ * The metatype getattro slot.
+ */
+static PyObject *sipWrapperType_getattro(PyObject *self, PyObject *name)
+{
+ if (add_all_lazy_attrs(((sipWrapperType *)self)->type) < 0)
+ return NULL;
+
+ return PyType_Type.tp_getattro(self, name);
+}
+
+
+/*
+ * The metatype setattro slot.
+ */
+static int sipWrapperType_setattro(PyObject *self, PyObject *name,
+ PyObject *value)
+{
+ if (add_all_lazy_attrs(((sipWrapperType *)self)->type) < 0)
+ return -1;
+
+ return PyType_Type.tp_setattro(self, name, value);
+}
+
+
+/*
+ * The instance new slot.
+ */
+static PyObject *sipSimpleWrapper_new(sipWrapperType *wt, PyObject *args,
+ PyObject *kwds)
+{
+ static PyObject *noargs = NULL;
+ sipTypeDef *td = wt->type;
+ sipContainerDef *cod;
+
+ /* Check the base types are not being used directly. */
+ if (wt == &sipSimpleWrapper_Type || wt == &sipWrapper_Type)
+ {
+ PyErr_Format(PyExc_TypeError,
+ "the %s type cannot be instantiated or sub-classed",
+ ((PyTypeObject *)wt)->tp_name);
+
+ return NULL;
+ }
+
+ if (sipTypeIsMapped(td))
+ cod = &((sipMappedTypeDef *)td)->mtd_container;
+ else
+ cod = &((sipClassTypeDef *)td)->ctd_container;
+
+ /* We need an empty tuple for an empty argument list. */
+ if (noargs == NULL)
+ {
+ noargs = PyTuple_New(0);
+
+ if (noargs == NULL)
+ return NULL;
+ }
+
+ /* See if it is a mapped type. */
+ if (sipTypeIsMapped(td))
+ {
+ PyErr_Format(PyExc_TypeError,
+ "%s.%s represents a mapped type and cannot be instantiated",
+ sipNameOfModule(td->td_module),
+ sipPyNameOfContainer(cod, td));
+
+ return NULL;
+ }
+
+ /* See if it is a namespace. */
+ if (sipTypeIsNamespace(td))
+ {
+ PyErr_Format(PyExc_TypeError,
+ "%s.%s represents a C++ namespace and cannot be instantiated",
+ sipNameOfModule(td->td_module),
+ sipPyNameOfContainer(cod, td));
+
+ return NULL;
+ }
+
+ /*
+ * See if the object is being created explicitly rather than being wrapped.
+ */
+ if (sipGetPending(NULL, NULL) == NULL)
+ {
+ /*
+ * See if it cannot be instantiated or sub-classed from Python, eg.
+ * it's an opaque class. Some restrictions might be overcome with
+ * better SIP support.
+ */
+ if (((sipClassTypeDef *)td)->ctd_init == NULL)
+ {
+ PyErr_Format(PyExc_TypeError,
+ "%s.%s cannot be instantiated or sub-classed",
+ sipNameOfModule(td->td_module),
+ sipPyNameOfContainer(cod, td));
+
+ return NULL;
+ }
+
+ /* See if it is an abstract type. */
+ if (sipTypeIsAbstract(td) && sipIsExactWrappedType(wt))
+ {
+ PyErr_Format(PyExc_TypeError,
+ "%s.%s represents a C++ abstract class and cannot be instantiated",
+ sipNameOfModule(td->td_module),
+ sipPyNameOfContainer(cod, td));
+
+ return NULL;
+ }
+ }
+
+ /* Call the standard super-type new. */
+ return PyBaseObject_Type.tp_new((PyTypeObject *)wt, noargs, NULL);
+}
+
+
+/*
+ * The instance init slot.
+ */
+static int sipSimpleWrapper_init(sipSimpleWrapper *self, PyObject *args,
+ PyObject *kwds)
+{
+ void *sipNew;
+ int sipFlags;
+ sipWrapper *owner;
+ sipWrapperType *wt = (sipWrapperType *)Py_TYPE(self);
+ sipTypeDef *td = wt->type;
+ sipClassTypeDef *ctd = (sipClassTypeDef *)td;
+ PyObject *unused, **unused_p;
+
+ static int got_kw_handler = FALSE;
+ static int (*kw_handler)(PyObject *, void *, PyObject *);
+
+ /*
+ * Get any keyword handler if necessary. In SIP v5 this will be
+ * generalised and not PyQt specific.
+ */
+ if (!got_kw_handler)
+ {
+ kw_handler = sip_api_import_symbol("pyqt_kw_handler");
+ got_kw_handler = TRUE;
+ }
+
+ /*
+ * We are interested in unused keyword arguments if we are creating a
+ * QObject and we have a handler.
+ */
+ unused_p = (kw_handler != NULL && isQObject((PyObject *)self)) ? &unused : NULL;
+ unused = NULL;
+
+ /* Check there is no existing C++ instance waiting to be wrapped. */
+ if ((sipNew = sipGetPending(&owner, &sipFlags)) == NULL)
+ {
+ PyObject *parseErr = NULL;
+
+ /* Call the C++ ctor. */
+ owner = NULL;
+
+ sipNew = ctd->ctd_init(self, args, kwds, unused_p, (PyObject **)&owner,
+ &parseErr);
+
+ if (sipNew != NULL)
+ {
+ sipFlags = SIP_DERIVED_CLASS;
+ }
+ else if (parseErr == NULL)
+ {
+ /*
+ * The C++ ctor must have raised an exception which has been
+ * translated to a Python exception.
+ */
+ return -1;
+ }
+ else
+ {
+ sipInitExtenderDef *ie = wt->iextend;
+
+ assert(parseErr != NULL);
+
+ /*
+ * If we have not found an appropriate overload then try any
+ * extenders.
+ */
+ while (PyList_Check(parseErr) && ie != NULL)
+ {
+ sipNew = ie->ie_extender(self, args, kwds, unused_p,
+ (PyObject **)&owner, &parseErr);
+
+ if (sipNew != NULL)
+ break;
+
+ ie = ie->ie_next;
+ }
+
+ if (sipNew == NULL)
+ {
+ const char *docstring = ctd->ctd_docstring;
+
+ /*
+ * Use the docstring for errors if it was automatically
+ * generated.
+ */
+ if (docstring != NULL)
+ {
+ if (*docstring == AUTO_DOCSTRING)
+ ++docstring;
+ else
+ docstring = NULL;
+ }
+
+ sip_api_no_function(parseErr,
+ sipPyNameOfContainer(&ctd->ctd_container, td),
+ docstring);
+
+ return -1;
+ }
+
+ sipFlags = 0;
+ }
+
+ if (owner == NULL)
+ sipFlags |= SIP_PY_OWNED;
+ else if ((PyObject *)owner == Py_None)
+ {
+ /* This is the hack that means that C++ owns the new instance. */
+ sipFlags |= SIP_CPP_HAS_REF;
+ Py_INCREF(self);
+ owner = NULL;
+ }
+ }
+
+ /*
+ * If there is an owner then we assume that the wrapper supports the
+ * concept.
+ */
+ if (owner != NULL)
+ {
+ assert(PyObject_TypeCheck((PyObject *)self, (PyTypeObject *)&sipWrapper_Type));
+ addToParent((sipWrapper *)self, (sipWrapper *)owner);
+ }
+
+ self->u.cppPtr = sipNew;
+ self->flags = sipFlags;
+
+ if (!sipNotInMap(self))
+ sipOMAddObject(&cppPyMap, self);
+
+ /* If we have unused keyword arguments then we know how to handle them. */
+ if (unused != NULL)
+ {
+ int rc;
+
+ rc = kw_handler((PyObject *)self, sipNew, unused);
+ Py_DECREF(unused);
+
+ if (rc < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/*
+ * The instance traverse slot.
+ */
+static int sipSimpleWrapper_traverse(sipSimpleWrapper *self, visitproc visit,
+ void *arg)
+{
+ int vret;
+ void *ptr;
+ const sipClassTypeDef *ctd;
+
+ /* Call the nearest handwritten traverse code in the class hierachy. */
+ if ((ptr = getPtrTypeDef(self, &ctd)) != NULL)
+ {
+ const sipClassTypeDef *sup_ctd = ctd;
+
+ if (ctd->ctd_traverse == NULL)
+ {
+ sipEncodedTypeDef *sup;
+
+ if ((sup = ctd->ctd_supers) != NULL)
+ do
+ sup_ctd = (sipClassTypeDef *)getGeneratedType(sup, ctd->ctd_base.td_module);
+ while (sup_ctd->ctd_traverse == NULL && !sup++->sc_flag);
+ }
+
+ if (sup_ctd->ctd_traverse != NULL)
+ if ((vret = sup_ctd->ctd_traverse(ptr, visit, arg)) != 0)
+ return vret;
+ }
+
+ if (self->dict != NULL)
+ if ((vret = visit(self->dict, arg)) != 0)
+ return vret;
+
+ if (self->extra_refs != NULL)
+ if ((vret = visit(self->extra_refs, arg)) != 0)
+ return vret;
+
+ if (self->user != NULL)
+ if ((vret = visit(self->user, arg)) != 0)
+ return vret;
+
+ return 0;
+}
+
+
+/*
+ * The instance clear slot.
+ */
+static int sipSimpleWrapper_clear(sipSimpleWrapper *self)
+{
+ int vret = 0;
+ void *ptr;
+ const sipClassTypeDef *ctd;
+ PyObject *tmp;
+
+ /* Call the nearest handwritten clear code in the class hierachy. */
+ if ((ptr = getPtrTypeDef(self, &ctd)) != NULL)
+ {
+ const sipClassTypeDef *sup_ctd = ctd;
+
+ if (ctd->ctd_clear == NULL)
+ {
+ sipEncodedTypeDef *sup;
+
+ if ((sup = ctd->ctd_supers) != NULL)
+ do
+ sup_ctd = (sipClassTypeDef *)getGeneratedType(sup, ctd->ctd_base.td_module);
+ while (sup_ctd->ctd_clear == NULL && !sup++->sc_flag);
+ }
+
+ if (sup_ctd->ctd_clear != NULL)
+ vret = sup_ctd->ctd_clear(ptr);
+ }
+
+ /* Remove the instance dictionary. */
+ tmp = self->dict;
+ self->dict = NULL;
+ Py_XDECREF(tmp);
+
+ /* Remove any extra references dictionary. */
+ tmp = self->extra_refs;
+ self->extra_refs = NULL;
+ Py_XDECREF(tmp);
+
+ /* Remove any user object. */
+ tmp = self->user;
+ self->user = NULL;
+ Py_XDECREF(tmp);
+
+ return vret;
+}
+
+
+#if PY_MAJOR_VERSION >= 3
+/*
+ * The instance get buffer slot for Python v3.
+ */
+static int sipSimpleWrapper_getbuffer(sipSimpleWrapper *self, Py_buffer *buf,
+ int flags)
+{
+ void *ptr;
+ const sipClassTypeDef *ctd;
+
+ if ((ptr = getPtrTypeDef(self, &ctd)) == NULL)
+ return -1;
+
+ return ctd->ctd_getbuffer((PyObject *)self, ptr, buf, flags);
+}
+#endif
+
+
+#if PY_MAJOR_VERSION >= 3
+/*
+ * The instance release buffer slot for Python v3.
+ */
+static void sipSimpleWrapper_releasebuffer(sipSimpleWrapper *self,
+ Py_buffer *buf)
+{
+ void *ptr;
+ const sipClassTypeDef *ctd;
+
+ if ((ptr = getPtrTypeDef(self, &ctd)) == NULL)
+ return -1;
+
+ return ctd->ctd_releasebuffer((PyObject *)self, ptr, buf);
+}
+#endif
+
+
+#if PY_MAJOR_VERSION < 3
+/*
+ * The instance read buffer slot for Python v2.
+ */
+static SIP_SSIZE_T sipSimpleWrapper_getreadbuffer(sipSimpleWrapper *self,
+ SIP_SSIZE_T segment, void **ptrptr)
+{
+ void *ptr;
+ const sipClassTypeDef *ctd;
+
+ if ((ptr = getPtrTypeDef(self, &ctd)) == NULL)
+ return -1;
+
+ return ctd->ctd_readbuffer((PyObject *)self, ptr, segment, ptrptr);
+}
+#endif
+
+
+#if PY_MAJOR_VERSION < 3
+/*
+ * The instance write buffer slot for Python v2.
+ */
+static SIP_SSIZE_T sipSimpleWrapper_getwritebuffer(sipSimpleWrapper *self,
+ SIP_SSIZE_T segment, void **ptrptr)
+{
+ void *ptr;
+ const sipClassTypeDef *ctd;
+
+ if ((ptr = getPtrTypeDef(self, &ctd)) == NULL)
+ return -1;
+
+ return ctd->ctd_writebuffer((PyObject *)self, ptr, segment, ptrptr);
+}
+#endif
+
+
+#if PY_MAJOR_VERSION < 3
+/*
+ * The instance segment count slot for Python v2.
+ */
+static SIP_SSIZE_T sipSimpleWrapper_getsegcount(sipSimpleWrapper *self,
+ SIP_SSIZE_T *lenp)
+{
+ void *ptr;
+ const sipClassTypeDef *ctd;
+
+ if ((ptr = getPtrTypeDef(self, &ctd)) == NULL)
+ return 0;
+
+ return ctd->ctd_segcount((PyObject *)self, ptr, lenp);
+}
+#endif
+
+
+#if PY_MAJOR_VERSION < 3
+/*
+ * The instance char buffer slot for Python v2.
+ */
+static SIP_SSIZE_T sipSimpleWrapper_getcharbuffer(sipSimpleWrapper *self,
+ SIP_SSIZE_T segment, void **ptrptr)
+{
+ void *ptr;
+ const sipClassTypeDef *ctd;
+
+ if ((ptr = getPtrTypeDef(self, &ctd)) == NULL)
+ return -1;
+
+ return ctd->ctd_charbuffer((PyObject *)self, ptr, segment, ptrptr);
+}
+#endif
+
+
+/*
+ * The instance dealloc slot.
+ */
+static void sipSimpleWrapper_dealloc(sipSimpleWrapper *self)
+{
+ forgetObject(self);
+
+ /*
+ * Now that the C++ object no longer exists we can tidy up the Python
+ * object. We used to do this first but that meant lambda slots were
+ * removed too soon (if they were connected to QObject.destroyed()).
+ */
+ sipSimpleWrapper_clear(self);
+
+ /* Call the standard super-type dealloc. */
+ PyBaseObject_Type.tp_dealloc((PyObject *)self);
+}
+
+
+/*
+ * The type call slot. Note that keyword arguments aren't supported.
+ */
+static PyObject *slot_call(PyObject *self,PyObject *args,PyObject *kw)
+{
+ PyObject *(*f)(PyObject *,PyObject *);
+
+ f = (PyObject *(*)(PyObject *,PyObject *))findSlot(self, call_slot);
+
+ assert(f != NULL);
+
+ return f(self,args);
+}
+
+
+/*
+ * The sequence type item slot.
+ */
+static PyObject *slot_sq_item(PyObject *self, SIP_SSIZE_T n)
+{
+ PyObject *(*f)(PyObject *,PyObject *);
+ PyObject *arg, *res;
+
+#if PY_MAJOR_VERSION >= 3
+ arg = PyLong_FromSsize_t(n);
+#elif PY_VERSION_HEX >= 0x02050000
+ arg = PyInt_FromSsize_t(n);
+#else
+ arg = PyInt_FromLong(n);
+#endif
+
+ if (arg == NULL)
+ return NULL;
+
+ f = (PyObject *(*)(PyObject *,PyObject *))findSlot(self, getitem_slot);
+
+ assert(f != NULL);
+
+ res = f(self,arg);
+
+ Py_DECREF(arg);
+
+ return res;
+}
+
+
+/*
+ * The mapping type assign subscript slot.
+ */
+static int slot_mp_ass_subscript(PyObject *self, PyObject *key,
+ PyObject *value)
+{
+ return objobjargprocSlot(self, key, value,
+ (value != NULL ? setitem_slot : delitem_slot));
+}
+
+
+/*
+ * The sequence type assign item slot.
+ */
+static int slot_sq_ass_item(PyObject *self, SIP_SSIZE_T i, PyObject *o)
+{
+ return ssizeobjargprocSlot(self, i, o,
+ (o != NULL ? setitem_slot : delitem_slot));
+}
+
+
+/*
+ * The type rich compare slot.
+ */
+static PyObject *slot_richcompare(PyObject *self, PyObject *arg, int op)
+{
+ PyObject *(*f)(PyObject *,PyObject *);
+ sipPySlotType st;
+
+ /* Convert the operation to a slot type. */
+ switch (op)
+ {
+ case Py_LT:
+ st = lt_slot;
+ break;
+
+ case Py_LE:
+ st = le_slot;
+ break;
+
+ case Py_EQ:
+ st = eq_slot;
+ break;
+
+ case Py_NE:
+ st = ne_slot;
+ break;
+
+ case Py_GT:
+ st = gt_slot;
+ break;
+
+ case Py_GE:
+ st = ge_slot;
+ break;
+ }
+
+ /* It might not exist if not all the above have been implemented. */
+ if ((f = (PyObject *(*)(PyObject *,PyObject *))findSlot(self, st)) == NULL)
+ {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ return f(self, arg);
+}
+
+
+/*
+ * The instance getattro slot.
+ */
+static PyObject *sipSimpleWrapper_getattro(PyObject *self, PyObject *name)
+{
+ if (add_all_lazy_attrs(((sipWrapperType *)Py_TYPE(self))->type) < 0)
+ return NULL;
+
+ return PyObject_GenericGetAttr(self, name);
+}
+
+
+/*
+ * The instance setattro slot.
+ */
+static int sipSimpleWrapper_setattro(PyObject *self, PyObject *name,
+ PyObject *value)
+{
+ if (add_all_lazy_attrs(((sipWrapperType *)Py_TYPE(self))->type) < 0)
+ return -1;
+
+ return PyObject_GenericSetAttr(self, name, value);
+}
+
+
+/*
+ * The __dict__ getter.
+ */
+static PyObject *sipSimpleWrapper_get_dict(PyObject *self, void *closure)
+{
+ sipSimpleWrapper *sw = (sipSimpleWrapper *)self;
+
+ /* Create the dictionary if needed. */
+ if (sw->dict == NULL)
+ {
+ sw->dict = PyDict_New();
+
+ if (sw->dict == NULL)
+ return NULL;
+ }
+
+ Py_INCREF(sw->dict);
+ return sw->dict;
+}
+
+
+/*
+ * The __dict__ setter.
+ */
+static int sipSimpleWrapper_set_dict(PyObject *self, PyObject *value,
+ void *closure)
+{
+ sipSimpleWrapper *sw = (sipSimpleWrapper *)self;
+
+ /* Check that any new value really is a dictionary. */
+ if (value != NULL && !PyDict_Check(value))
+ {
+ PyErr_Format(PyExc_TypeError,
+ "__dict__ must be set to a dictionary, not a '%s'",
+ Py_TYPE(value)->tp_name);
+ return -1;
+ }
+
+ Py_XDECREF(sw->dict);
+
+ Py_XINCREF(value);
+ sw->dict = value;
+
+ return 0;
+}
+
+
+/*
+ * The table of getters and setters.
+ */
+static PyGetSetDef sipSimpleWrapper_getset[] = {
+ {(char *)"__dict__", sipSimpleWrapper_get_dict, sipSimpleWrapper_set_dict,
+ NULL, NULL},
+ {NULL, NULL, NULL, NULL, NULL}
+};
+
+
+/*
+ * The type data structure. Note that we pretend to be a mapping object and a
+ * sequence object at the same time. Python will choose one over another,
+ * depending on the context, but we implement as much as we can and don't make
+ * assumptions about which Python will choose.
+ */
+sipWrapperType sipSimpleWrapper_Type = {
+#if !defined(STACKLESS)
+ {
+#endif
+ {
+ PyVarObject_HEAD_INIT(&sipWrapperType_Type, 0)
+ "sip.simplewrapper", /* tp_name */
+ sizeof (sipSimpleWrapper), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)sipSimpleWrapper_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved (Python v3), tp_compare (Python v2) */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ sipSimpleWrapper_getattro, /* tp_getattro */
+ sipSimpleWrapper_setattro, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
+ 0, /* tp_doc */
+ (traverseproc)sipSimpleWrapper_traverse, /* tp_traverse */
+ (inquiry)sipSimpleWrapper_clear, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ sipSimpleWrapper_getset, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ offsetof(sipSimpleWrapper, dict), /* tp_dictoffset */
+ (initproc)sipSimpleWrapper_init, /* tp_init */
+ 0, /* tp_alloc */
+ (newfunc)sipSimpleWrapper_new, /* tp_new */
+ 0, /* tp_free */
+ },
+#if !defined(STACKLESS)
+ },
+#endif
+ 0,
+ 0
+};
+
+
+/*
+ * The wrapper clear slot.
+ */
+static int sipWrapper_clear(sipWrapper *self)
+{
+ int vret;
+ sipSimpleWrapper *sw = (sipSimpleWrapper *)self;
+
+ vret = sipSimpleWrapper_clear(sw);
+
+ /* Remove any slots connected via a proxy. */
+ if (sipQtSupport != NULL && sipPossibleProxy(sw))
+ {
+ void *tx = sipGetAddress(sw);
+
+ if (tx != NULL)
+ {
+ sipSlot *slot;
+ void *context = NULL;
+
+ while ((slot = sipQtSupport->qt_find_sipslot(tx, &context)) != NULL)
+ {
+ sip_api_clear_any_slot_reference(slot);
+
+ if (context == NULL)
+ break;
+ }
+ }
+ }
+
+ /* Detach children (which will be owned by C/C++). */
+ while ((sw = (sipSimpleWrapper *)self->first_child) != NULL)
+ {
+ /*
+ * Although this object is being garbage collected it doesn't follow
+ * that it's children should be. So we make sure that the child stays
+ * alive and remember we have done so.
+ */
+ Py_INCREF(sw);
+ sipSetCppHasRef(sw);
+
+ removeFromParent(self->first_child);
+ }
+
+ return vret;
+}
+
+
+/*
+ * The wrapper dealloc slot.
+ */
+static void sipWrapper_dealloc(sipWrapper *self)
+{
+ /*
+ * We can't simply call the super-type because things have to be done in a
+ * certain order. The first thing is to get rid of the wrapped instance.
+ */
+ forgetObject((sipSimpleWrapper *)self);
+
+ sipWrapper_clear(self);
+
+ /* Skip the super-type's dealloc. */
+ PyBaseObject_Type.tp_dealloc((PyObject *)self);
+}
+
+
+/*
+ * The wrapper traverse slot.
+ */
+static int sipWrapper_traverse(sipWrapper *self, visitproc visit, void *arg)
+{
+ int vret;
+ sipSimpleWrapper *sw = (sipSimpleWrapper *)self;
+ sipWrapper *w;
+
+ if ((vret = sipSimpleWrapper_traverse(sw, visit, arg)) != 0)
+ return vret;
+
+ /* This should be handwritten code in PyQt. */
+ if (sipQtSupport != NULL)
+ {
+ void *tx = sipGetAddress(sw);
+
+ if (tx != NULL)
+ {
+ sipSlot *slot;
+ void *context = NULL;
+
+ while ((slot = sipQtSupport->qt_find_sipslot(tx, &context)) != NULL)
+ {
+ if ((vret = sip_api_visit_slot(slot, visit, arg)) != 0)
+ return vret;
+
+ if (context == NULL)
+ break;
+ }
+ }
+ }
+
+ for (w = self->first_child; w != NULL; w = w->sibling_next)
+ {
+ /*
+ * We don't traverse if the wrapper is a child of itself. We do this
+ * so that wrapped objects returned by virtual methods with the
+ * /Factory/ don't have those objects collected. This then means that
+ * plugins implemented in Python have a chance of working.
+ */
+ if (w != self)
+ if ((vret = visit((PyObject *)w, arg)) != 0)
+ return vret;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Add the slots for a class type and all its super-types.
+ */
+static void addClassSlots(sipWrapperType *wt, sipClassTypeDef *ctd)
+{
+ /* Add the buffer interface. */
+#if PY_MAJOR_VERSION >= 3
+ if (ctd->ctd_getbuffer != NULL)
+ wt->super.as_buffer.bf_getbuffer = (getbufferproc)sipSimpleWrapper_getbuffer;
+
+ if (ctd->ctd_releasebuffer != NULL)
+ wt->super.as_buffer.bf_releasebuffer = (releasebufferproc)sipSimpleWrapper_releasebuffer;
+#else
+ if (ctd->ctd_readbuffer != NULL)
+#if PY_VERSION_HEX >= 0x02050000
+ wt->super.as_buffer.bf_getreadbuffer = (readbufferproc)sipSimpleWrapper_getreadbuffer;
+#else
+ wt->super.as_buffer.bf_getreadbuffer = (getreadbufferproc)sipSimpleWrapper_getreadbuffer;
+#endif
+
+ if (ctd->ctd_writebuffer != NULL)
+#if PY_VERSION_HEX >= 0x02050000
+ wt->super.as_buffer.bf_getwritebuffer = (writebufferproc)sipSimpleWrapper_getwritebuffer;
+#else
+ wt->super.as_buffer.bf_getwritebuffer = (getwritebufferproc)sipSimpleWrapper_getwritebuffer;
+#endif
+
+ if (ctd->ctd_segcount != NULL)
+#if PY_VERSION_HEX >= 0x02050000
+ wt->super.as_buffer.bf_getsegcount = (segcountproc)sipSimpleWrapper_getsegcount;
+#else
+ wt->super.as_buffer.bf_getsegcount = (getsegcountproc)sipSimpleWrapper_getsegcount;
+#endif
+
+ if (ctd->ctd_charbuffer != NULL)
+#if PY_VERSION_HEX >= 0x02050000
+ wt->super.as_buffer.bf_getcharbuffer = (charbufferproc)sipSimpleWrapper_getcharbuffer;
+#else
+ wt->super.as_buffer.bf_getcharbuffer = (getcharbufferproc)sipSimpleWrapper_getcharbuffer;
+#endif
+#endif
+
+ /* Add the slots for this type. */
+ if (ctd->ctd_pyslots != NULL)
+ addTypeSlots(&wt->super, ctd->ctd_pyslots);
+}
+
+
+/*
+ * Add the slot handler for each slot present in the type.
+ */
+static void addTypeSlots(PyHeapTypeObject *heap_to, sipPySlotDef *slots)
+{
+ PyTypeObject *to;
+ PyNumberMethods *nb;
+ PySequenceMethods *sq;
+ PyMappingMethods *mp;
+ void *f;
+
+ to = (PyTypeObject *)heap_to;
+ nb = &heap_to->as_number;
+ sq = &heap_to->as_sequence;
+ mp = &heap_to->as_mapping;
+
+ while ((f = slots->psd_func) != NULL)
+ switch (slots++->psd_type)
+ {
+ case str_slot:
+ to->tp_str = (reprfunc)f;
+ break;
+
+ case int_slot:
+ if (nb != NULL)
+ nb->nb_int = (unaryfunc)f;
+ break;
+
+#if PY_MAJOR_VERSION < 3
+ case long_slot:
+ if (nb != NULL)
+ nb->nb_long = (unaryfunc)f;
+ break;
+#endif
+
+ case float_slot:
+ if (nb != NULL)
+ nb->nb_float = (unaryfunc)f;
+ break;
+
+ case len_slot:
+ if (mp != NULL)
+#if PY_VERSION_HEX >= 0x02050000
+ mp->mp_length = (lenfunc)f;
+#else
+ mp->mp_length = (inquiry)f;
+#endif
+ if (sq != NULL)
+#if PY_VERSION_HEX >= 0x02050000
+ sq->sq_length = (lenfunc)f;
+#else
+ sq->sq_length = (inquiry)f;
+#endif
+ break;
+
+ case contains_slot:
+ if (sq != NULL)
+ sq->sq_contains = (objobjproc)f;
+ break;
+
+ case add_slot:
+ if (nb != NULL)
+ nb->nb_add = (binaryfunc)f;
+ break;
+
+ case concat_slot:
+ if (sq != NULL)
+ sq->sq_concat = (binaryfunc)f;
+ break;
+
+ case sub_slot:
+ if (nb != NULL)
+ nb->nb_subtract = (binaryfunc)f;
+ break;
+
+ case mul_slot:
+ if (nb != NULL)
+ nb->nb_multiply = (binaryfunc)f;
+ break;
+
+ case repeat_slot:
+ if (sq != NULL)
+#if PY_VERSION_HEX >= 0x02050000
+ sq->sq_repeat = (ssizeargfunc)f;
+#else
+ sq->sq_repeat = (intargfunc)f;
+#endif
+ break;
+
+ case div_slot:
+ if (nb != NULL)
+ {
+ nb->nb_true_divide = (binaryfunc)f;
+#if PY_MAJOR_VERSION < 3
+ nb->nb_divide = (binaryfunc)f;
+#endif
+ }
+ break;
+
+ case mod_slot:
+ if (nb != NULL)
+ nb->nb_remainder = (binaryfunc)f;
+ break;
+
+ case floordiv_slot:
+ if (nb != NULL)
+ nb->nb_floor_divide = (binaryfunc)f;
+ break;
+
+ case truediv_slot:
+ if (nb != NULL)
+ nb->nb_true_divide = (binaryfunc)f;
+ break;
+
+ case and_slot:
+ if (nb != NULL)
+ nb->nb_and = (binaryfunc)f;
+ break;
+
+ case or_slot:
+ if (nb != NULL)
+ nb->nb_or = (binaryfunc)f;
+ break;
+
+ case xor_slot:
+ if (nb != NULL)
+ nb->nb_xor = (binaryfunc)f;
+ break;
+
+ case lshift_slot:
+ if (nb != NULL)
+ nb->nb_lshift = (binaryfunc)f;
+ break;
+
+ case rshift_slot:
+ if (nb != NULL)
+ nb->nb_rshift = (binaryfunc)f;
+ break;
+
+ case iadd_slot:
+ if (nb != NULL)
+ nb->nb_inplace_add = (binaryfunc)f;
+ break;
+
+ case iconcat_slot:
+ if (sq != NULL)
+ sq->sq_inplace_concat = (binaryfunc)f;
+ break;
+
+ case isub_slot:
+ if (nb != NULL)
+ nb->nb_inplace_subtract = (binaryfunc)f;
+ break;
+
+ case imul_slot:
+ if (nb != NULL)
+ nb->nb_inplace_multiply = (binaryfunc)f;
+ break;
+
+ case irepeat_slot:
+ if (sq != NULL)
+#if PY_VERSION_HEX >= 0x02050000
+ sq->sq_inplace_repeat = (ssizeargfunc)f;
+#else
+ sq->sq_inplace_repeat = (intargfunc)f;
+#endif
+ break;
+
+ case idiv_slot:
+ if (nb != NULL)
+ {
+ nb->nb_inplace_true_divide = (binaryfunc)f;
+#if PY_MAJOR_VERSION < 3
+ nb->nb_inplace_divide = (binaryfunc)f;
+#endif
+ }
+ break;
+
+ case imod_slot:
+ if (nb != NULL)
+ nb->nb_inplace_remainder = (binaryfunc)f;
+ break;
+
+ case ifloordiv_slot:
+ if (nb != NULL)
+ nb->nb_inplace_floor_divide = (binaryfunc)f;
+ break;
+
+ case itruediv_slot:
+ if (nb != NULL)
+ nb->nb_inplace_true_divide = (binaryfunc)f;
+ break;
+
+ case iand_slot:
+ if (nb != NULL)
+ nb->nb_inplace_and = (binaryfunc)f;
+ break;
+
+ case ior_slot:
+ if (nb != NULL)
+ nb->nb_inplace_or = (binaryfunc)f;
+ break;
+
+ case ixor_slot:
+ if (nb != NULL)
+ nb->nb_inplace_xor = (binaryfunc)f;
+ break;
+
+ case ilshift_slot:
+ if (nb != NULL)
+ nb->nb_inplace_lshift = (binaryfunc)f;
+ break;
+
+ case irshift_slot:
+ if (nb != NULL)
+ nb->nb_inplace_rshift = (binaryfunc)f;
+ break;
+
+ case invert_slot:
+ if (nb != NULL)
+ nb->nb_invert = (unaryfunc)f;
+ break;
+
+ case call_slot:
+ to->tp_call = slot_call;
+ break;
+
+ case getitem_slot:
+ if (mp != NULL)
+ mp->mp_subscript = (binaryfunc)f;
+ if (sq != NULL)
+ sq->sq_item = slot_sq_item;
+ break;
+
+ case setitem_slot:
+ case delitem_slot:
+ if (mp != NULL)
+ mp->mp_ass_subscript = slot_mp_ass_subscript;
+ if (sq != NULL)
+ sq->sq_ass_item = slot_sq_ass_item;
+ break;
+
+ case lt_slot:
+ case le_slot:
+ case eq_slot:
+ case ne_slot:
+ case gt_slot:
+ case ge_slot:
+ to->tp_richcompare = slot_richcompare;
+ break;
+
+#if PY_MAJOR_VERSION < 3
+ case cmp_slot:
+ to->tp_compare = (cmpfunc)f;
+ break;
+#endif
+
+ case bool_slot:
+ if (nb != NULL)
+#if PY_MAJOR_VERSION >= 3
+ nb->nb_bool = (inquiry)f;
+#else
+ nb->nb_nonzero = (inquiry)f;
+#endif
+ break;
+
+ case neg_slot:
+ if (nb != NULL)
+ nb->nb_negative = (unaryfunc)f;
+ break;
+
+ case repr_slot:
+ to->tp_repr = (reprfunc)f;
+ break;
+
+ case hash_slot:
+ to->tp_hash = (hashfunc)f;
+ break;
+
+ case pos_slot:
+ if (nb != NULL)
+ nb->nb_positive = (unaryfunc)f;
+ break;
+
+ case abs_slot:
+ if (nb != NULL)
+ nb->nb_absolute = (unaryfunc)f;
+ break;
+
+#if PY_VERSION_HEX >= 0x02050000
+ case index_slot:
+ if (nb != NULL)
+ nb->nb_index = (unaryfunc)f;
+ break;
+#endif
+
+ case iter_slot:
+ to->tp_iter = (getiterfunc)f;
+ break;
+
+ case next_slot:
+ to->tp_iternext = (iternextfunc)f;
+ break;
+ }
+}
+
+
+/*
+ * Remove the object from the map and call the C/C++ dtor if we own the
+ * instance.
+ */
+static void forgetObject(sipSimpleWrapper *sw)
+{
+ const sipClassTypeDef *ctd;
+
+ /*
+ * This is needed because we release the GIL when calling a C++ dtor.
+ * Without it the cyclic garbage collector can be invoked from another
+ * thread resulting in a crash.
+ */
+ PyObject_GC_UnTrack((PyObject *)sw);
+
+ if (getPtrTypeDef(sw, &ctd) != NULL)
+ {
+ /*
+ * Remove the object from the map before calling the class specific
+ * dealloc code. This code calls the C++ dtor and may result in
+ * further calls that pass the instance as an argument. If this is
+ * still in the map then it's reference count would be increased (to
+ * one) and bad things happen when it drops back to zero again. (An
+ * example is PyQt events generated during the dtor call being passed
+ * to an event filter implemented in Python.) By removing it from the
+ * map first we ensure that a new Python object is created.
+ */
+ sipOMRemoveObject(&cppPyMap, sw);
+
+ /* Call the C++ dtor if there is one. */
+ if (ctd->ctd_dealloc != NULL)
+ ctd->ctd_dealloc(sw);
+ }
+}
+
+
+/*
+ * If the given name is that of a typedef then the corresponding type is
+ * returned.
+ */
+static const char *sip_api_resolve_typedef(const char *name)
+{
+ const sipExportedModuleDef *em;
+
+ /*
+ * Note that if the same name is defined as more than one type (which is
+ * possible if more than one completely independent modules are being
+ * used) then we might pick the wrong one.
+ */
+ for (em = moduleList; em != NULL; em = em->em_next)
+ {
+ if (em->em_nrtypedefs > 0)
+ {
+ sipTypedefDef *tdd;
+
+ tdd = (sipTypedefDef *)bsearch(name, em->em_typedefs,
+ em->em_nrtypedefs, sizeof (sipTypedefDef),
+ compareTypedefName);
+
+ if (tdd != NULL)
+ return tdd->tdd_type_name;
+ }
+ }
+
+ return NULL;
+}
+
+
+/*
+ * The bsearch() helper function for searching a sorted typedef table.
+ */
+static int compareTypedefName(const void *key, const void *el)
+{
+ return strcmp((const char *)key, ((const sipTypedefDef *)el)->tdd_name);
+}
+
+
+/*
+ * Add the given Python object to the given list. Return 0 if there was no
+ * error.
+ */
+static int addPyObjectToList(sipPyObject **head, PyObject *object)
+{
+ sipPyObject *po;
+
+ if ((po = sip_api_malloc(sizeof (sipPyObject))) == NULL)
+ return -1;
+
+ po->object = object;
+ po->next = *head;
+
+ *head = po;
+
+ return 0;
+}
+
+
+/*
+ * Register a symbol with a name. A negative value is returned if the name was
+ * already registered.
+ */
+static int sip_api_export_symbol(const char *name, void *sym)
+{
+ sipSymbol *ss;
+
+ if (sip_api_import_symbol(name) != NULL)
+ return -1;
+
+ if ((ss = sip_api_malloc(sizeof (sipSymbol))) == NULL)
+ return -1;
+
+ ss->name = name;
+ ss->symbol = sym;
+ ss->next = sipSymbolList;
+
+ sipSymbolList = ss;
+
+ return 0;
+}
+
+
+/*
+ * Return the symbol registered with the given name. NULL is returned if the
+ * name was not registered.
+ */
+static void *sip_api_import_symbol(const char *name)
+{
+ sipSymbol *ss;
+
+ for (ss = sipSymbolList; ss != NULL; ss = ss->next)
+ if (strcmp(ss->name, name) == 0)
+ return ss->symbol;
+
+ return NULL;
+}
+
+
+/*
+ * Visit a slot connected to an object for the cyclic garbage collector. This
+ * is only called externally by PyQt3.
+ */
+static int sip_api_visit_slot(sipSlot *slot, visitproc visit, void *arg)
+{
+ /* See if the slot has an extra reference. */
+ if (slot->weakSlot == Py_True && slot->pyobj != Py_None)
+ return visit(slot->pyobj, arg);
+
+ return 0;
+}
+
+
+/*
+ * Clear a slot if it has an extra reference to keep it alive. This is only
+ * called externally by PyQt3.
+ */
+static void sip_api_clear_any_slot_reference(sipSlot *slot)
+{
+ if (slot->weakSlot == Py_True)
+ {
+ PyObject *xref = slot->pyobj;
+
+ /*
+ * Replace the slot with None. We don't use NULL as this has another
+ * meaning.
+ */
+ Py_INCREF(Py_None);
+ slot->pyobj = Py_None;
+
+ Py_DECREF(xref);
+ }
+}
+
+
+/*
+ * Convert a Python object to a character and raise an exception if there was
+ * an error.
+ */
+static char sip_api_bytes_as_char(PyObject *obj)
+{
+ char ch;
+
+ if (parseBytes_AsChar(obj, &ch) < 0)
+ {
+ PyErr_Format(PyExc_TypeError,
+#if PY_MAJOR_VERSION >= 3
+ "bytes of length 1 expected not '%s'",
+#else
+ "string of length 1 expected not '%s'",
+#endif
+ Py_TYPE(obj)->tp_name);
+
+ return '\0';
+ }
+
+ return ch;
+}
+
+
+/*
+ * Convert a Python object to a string and raise an exception if there was
+ * an error.
+ */
+static const char *sip_api_bytes_as_string(PyObject *obj)
+{
+ const char *a;
+
+ if (parseBytes_AsString(obj, &a) < 0)
+ {
+ PyErr_Format(PyExc_TypeError,
+#if PY_MAJOR_VERSION >= 3
+ "bytes expected not '%s'",
+#else
+ "string expected not '%s'",
+#endif
+ Py_TYPE(obj)->tp_name);
+
+ return NULL;
+ }
+
+ return a;
+}
+
+
+/*
+ * Convert a Python ASCII string object to a character and raise an exception
+ * if there was an error.
+ */
+static char sip_api_string_as_ascii_char(PyObject *obj)
+{
+ char ch;
+
+ if (parseString_AsASCIIChar(obj, &ch) < 0)
+ {
+ /* Use the exception set if it was an encoding error. */
+ if (!PyUnicode_Check(obj) || PyUnicode_GET_SIZE(obj) != 1)
+ PyErr_Format(PyExc_TypeError,
+#if PY_MAJOR_VERSION >= 3
+ "bytes or ASCII string of length 1 expected not '%s'",
+#else
+ "string or ASCII unicode of length 1 expected not '%s'",
+#endif
+ Py_TYPE(obj)->tp_name);
+
+ return '\0';
+ }
+
+ return ch;
+}
+
+
+/*
+ * Parse an ASCII character and return it.
+ */
+static int parseString_AsASCIIChar(PyObject *obj, char *ap)
+{
+ return parseString_AsEncodedChar(PyUnicode_AsASCIIString(obj), obj, ap);
+}
+
+
+/*
+ * Convert a Python Latin-1 string object to a character and raise an exception
+ * if there was an error.
+ */
+static char sip_api_string_as_latin1_char(PyObject *obj)
+{
+ char ch;
+
+ if (parseString_AsLatin1Char(obj, &ch) < 0)
+ {
+ /* Use the exception set if it was an encoding error. */
+ if (!PyUnicode_Check(obj) || PyUnicode_GET_SIZE(obj) != 1)
+ PyErr_Format(PyExc_TypeError,
+#if PY_MAJOR_VERSION >= 3
+ "bytes or Latin-1 string of length 1 expected not '%s'",
+#else
+ "string or Latin-1 unicode of length 1 expected not '%s'",
+#endif
+ Py_TYPE(obj)->tp_name);
+
+ return '\0';
+ }
+
+ return ch;
+}
+
+
+/*
+ * Parse a Latin-1 character and return it.
+ */
+static int parseString_AsLatin1Char(PyObject *obj, char *ap)
+{
+ return parseString_AsEncodedChar(PyUnicode_AsLatin1String(obj), obj, ap);
+}
+
+
+/*
+ * Convert a Python UTF-8 string object to a character and raise an exception
+ * if there was an error.
+ */
+static char sip_api_string_as_utf8_char(PyObject *obj)
+{
+ char ch;
+
+ if (parseString_AsUTF8Char(obj, &ch) < 0)
+ {
+ /* Use the exception set if it was an encoding error. */
+ if (!PyUnicode_Check(obj) || PyUnicode_GET_SIZE(obj) != 1)
+ PyErr_Format(PyExc_TypeError,
+#if PY_MAJOR_VERSION >= 3
+ "bytes or UTF-8 string of length 1 expected not '%s'",
+#else
+ "string or UTF-8 unicode of length 1 expected not '%s'",
+#endif
+ Py_TYPE(obj)->tp_name);
+
+ return '\0';
+ }
+
+ return ch;
+}
+
+
+/*
+ * Parse a UTF-8 character and return it.
+ */
+static int parseString_AsUTF8Char(PyObject *obj, char *ap)
+{
+ return parseString_AsEncodedChar(PyUnicode_AsUTF8String(obj), obj, ap);
+}
+
+
+/*
+ * Parse an encoded character and return it.
+ */
+static int parseString_AsEncodedChar(PyObject *bytes, PyObject *obj, char *ap)
+{
+ SIP_SSIZE_T size;
+
+ if (bytes == NULL)
+ {
+ PyErr_Clear();
+
+ return parseBytes_AsChar(obj, ap);
+ }
+
+ size = SIPBytes_GET_SIZE(bytes);
+
+ if (size != 1)
+ {
+ Py_DECREF(bytes);
+ return -1;
+ }
+
+ *ap = *SIPBytes_AS_STRING(bytes);
+
+ Py_DECREF(bytes);
+
+ return 0;
+}
+
+
+/*
+ * Convert a Python ASCII string object to a string and raise an exception if
+ * there was an error. The object is updated with the one that owns the
+ * string. Note that None is considered an error.
+ */
+static const char *sip_api_string_as_ascii_string(PyObject **obj)
+{
+ PyObject *s = *obj;
+ const char *a;
+
+ if (s == Py_None || (*obj = parseString_AsASCIIString(s, &a)) == NULL)
+ {
+ /* Use the exception set if it was an encoding error. */
+ if (!PyUnicode_Check(s))
+ PyErr_Format(PyExc_TypeError,
+#if PY_MAJOR_VERSION >= 3
+ "bytes or ASCII string expected not '%s'",
+#else
+ "string or ASCII unicode expected not '%s'",
+#endif
+ Py_TYPE(s)->tp_name);
+
+ return NULL;
+ }
+
+ return a;
+}
+
+
+/*
+ * Parse an ASCII string and return it and a new reference to the object that
+ * owns the string.
+ */
+static PyObject *parseString_AsASCIIString(PyObject *obj, const char **ap)
+{
+ return parseString_AsEncodedString(PyUnicode_AsASCIIString(obj), obj, ap);
+}
+
+
+/*
+ * Convert a Python Latin-1 string object to a string and raise an exception if
+ * there was an error. The object is updated with the one that owns the
+ * string. Note that None is considered an error.
+ */
+static const char *sip_api_string_as_latin1_string(PyObject **obj)
+{
+ PyObject *s = *obj;
+ const char *a;
+
+ if (s == Py_None || (*obj = parseString_AsLatin1String(s, &a)) == NULL)
+ {
+ /* Use the exception set if it was an encoding error. */
+ if (!PyUnicode_Check(s))
+ PyErr_Format(PyExc_TypeError,
+#if PY_MAJOR_VERSION >= 3
+ "bytes or Latin-1 string expected not '%s'",
+#else
+ "string or Latin-1 unicode expected not '%s'",
+#endif
+ Py_TYPE(s)->tp_name);
+
+ return NULL;
+ }
+
+ return a;
+}
+
+
+/*
+ * Parse a Latin-1 string and return it and a new reference to the object that
+ * owns the string.
+ */
+static PyObject *parseString_AsLatin1String(PyObject *obj, const char **ap)
+{
+ return parseString_AsEncodedString(PyUnicode_AsLatin1String(obj), obj, ap);
+}
+
+
+/*
+ * Convert a Python UTF-8 string object to a string and raise an exception if
+ * there was an error. The object is updated with the one that owns the
+ * string. Note that None is considered an error.
+ */
+static const char *sip_api_string_as_utf8_string(PyObject **obj)
+{
+ PyObject *s = *obj;
+ const char *a;
+
+ if (s == Py_None || (*obj = parseString_AsUTF8String(s, &a)) == NULL)
+ {
+ /* Use the exception set if it was an encoding error. */
+ if (!PyUnicode_Check(s))
+ PyErr_Format(PyExc_TypeError,
+#if PY_MAJOR_VERSION >= 3
+ "bytes or UTF-8 string expected not '%s'",
+#else
+ "string or UTF-8 unicode expected not '%s'",
+#endif
+ Py_TYPE(s)->tp_name);
+
+ return NULL;
+ }
+
+ return a;
+}
+
+
+/*
+ * Parse a UTF-8 string and return it and a new reference to the object that
+ * owns the string.
+ */
+static PyObject *parseString_AsUTF8String(PyObject *obj, const char **ap)
+{
+ return parseString_AsEncodedString(PyUnicode_AsUTF8String(obj), obj, ap);
+}
+
+
+/*
+ * Parse an encoded string and return it and a new reference to the object that
+ * owns the string.
+ */
+static PyObject *parseString_AsEncodedString(PyObject *bytes, PyObject *obj,
+ const char **ap)
+{
+ if (bytes != NULL)
+ {
+ *ap = SIPBytes_AS_STRING(bytes);
+
+ return bytes;
+ }
+
+ PyErr_Clear();
+
+ if (parseBytes_AsString(obj, ap) < 0)
+ return NULL;
+
+ Py_INCREF(obj);
+
+ return obj;
+}
+
+
+/*
+ * Parse a character array and return it's address and length.
+ */
+static int parseBytes_AsCharArray(PyObject *obj, const char **ap,
+ SIP_SSIZE_T *aszp)
+{
+ if (obj == Py_None)
+ {
+ *ap = NULL;
+ *aszp = 0;
+ }
+ else if (SIPBytes_Check(obj))
+ {
+ *ap = SIPBytes_AS_STRING(obj);
+ *aszp = SIPBytes_GET_SIZE(obj);
+ }
+ else if (PyObject_AsCharBuffer(obj, ap, aszp) < 0)
+ return -1;
+
+ return 0;
+}
+
+
+/*
+ * Parse a character and return it.
+ */
+static int parseBytes_AsChar(PyObject *obj, char *ap)
+{
+ const char *chp;
+ SIP_SSIZE_T sz;
+
+ if (SIPBytes_Check(obj))
+ {
+ chp = SIPBytes_AS_STRING(obj);
+ sz = SIPBytes_GET_SIZE(obj);
+ }
+ else if (PyObject_AsCharBuffer(obj, &chp, &sz) < 0)
+ return -1;
+
+ if (sz != 1)
+ return -1;
+
+ *ap = *chp;
+
+ return 0;
+}
+
+
+/*
+ * Parse a character string and return it.
+ */
+static int parseBytes_AsString(PyObject *obj, const char **ap)
+{
+ SIP_SSIZE_T sz;
+
+ return parseBytes_AsCharArray(obj, ap, &sz);
+}
+
+
+#if defined(HAVE_WCHAR_H)
+/*
+ * Convert a Python object to a wide character.
+ */
+static wchar_t sip_api_unicode_as_wchar(PyObject *obj)
+{
+ wchar_t ch;
+
+ if (parseWChar(obj, &ch) < 0)
+ {
+ PyErr_Format(PyExc_ValueError,
+#if PY_MAJOR_VERSION >= 3
+ "string"
+#else
+ "unicode string"
+#endif
+ " of length 1 expected, not %s", Py_TYPE(obj)->tp_name);
+
+ return L'\0';
+ }
+
+ return ch;
+}
+
+
+/*
+ * Convert a Python object to a wide character string on the heap.
+ */
+static wchar_t *sip_api_unicode_as_wstring(PyObject *obj)
+{
+ wchar_t *p;
+
+ if (parseWCharString(obj, &p) < 0)
+ {
+ PyErr_Format(PyExc_ValueError,
+#if PY_MAJOR_VERSION >= 3
+ "string"
+#else
+ "unicode string"
+#endif
+ " expected, not %s", Py_TYPE(obj)->tp_name);
+
+ return NULL;
+ }
+
+ return p;
+}
+
+
+/*
+ * Parse a wide character array and return it's address and length.
+ */
+static int parseWCharArray(PyObject *obj, wchar_t **ap, SIP_SSIZE_T *aszp)
+{
+ if (obj == Py_None)
+ {
+ *ap = NULL;
+ *aszp = 0;
+
+ return 0;
+ }
+
+ if (PyUnicode_Check(obj))
+ return convertToWCharArray(obj, ap, aszp);
+
+#if PY_MAJOR_VERSION < 3
+ if (PyString_Check(obj))
+ {
+ int rc;
+ PyObject *uobj;
+
+ if ((uobj = PyUnicode_FromObject(obj)) == NULL)
+ return -1;
+
+ rc = convertToWCharArray(uobj, ap, aszp);
+ Py_DECREF(uobj);
+
+ return rc;
+ }
+#endif
+
+ return -1;
+}
+
+
+/*
+ * Convert a Unicode object to a wide character array and return it's address
+ * and length.
+ */
+static int convertToWCharArray(PyObject *obj, wchar_t **ap, SIP_SSIZE_T *aszp)
+{
+ SIP_SSIZE_T ulen;
+ wchar_t *wc;
+
+ ulen = PyUnicode_GET_SIZE(obj);
+
+ if ((wc = sip_api_malloc(ulen * sizeof (wchar_t))) == NULL)
+ return -1;
+
+ ulen = PyUnicode_AsWideChar((PyUnicodeObject *)obj, wc, ulen);
+
+ if (ulen < 0)
+ {
+ sip_api_free(wc);
+ return -1;
+ }
+
+ *ap = wc;
+ *aszp = ulen;
+
+ return 0;
+}
+
+
+/*
+ * Parse a wide character and return it.
+ */
+static int parseWChar(PyObject *obj, wchar_t *ap)
+{
+ if (PyUnicode_Check(obj))
+ return convertToWChar(obj, ap);
+
+#if PY_MAJOR_VERSION < 3
+ if (PyString_Check(obj))
+ {
+ int rc;
+ PyObject *uobj;
+
+ if ((uobj = PyUnicode_FromObject(obj)) == NULL)
+ return -1;
+
+ rc = convertToWChar(uobj, ap);
+ Py_DECREF(uobj);
+
+ return rc;
+ }
+#endif
+
+ return -1;
+}
+
+
+/*
+ * Convert a Unicode object to a wide character and return it.
+ */
+static int convertToWChar(PyObject *obj, wchar_t *ap)
+{
+ if (PyUnicode_GET_SIZE(obj) != 1)
+ return -1;
+
+ if (PyUnicode_AsWideChar((PyUnicodeObject *)obj, ap, 1) != 1)
+ return -1;
+
+ return 0;
+}
+
+
+/*
+ * Parse a wide character string and return a copy on the heap.
+ */
+static int parseWCharString(PyObject *obj, wchar_t **ap)
+{
+ if (obj == Py_None)
+ {
+ *ap = NULL;
+
+ return 0;
+ }
+
+ if (PyUnicode_Check(obj))
+ return convertToWCharString(obj, ap);
+
+#if PY_MAJOR_VERSION < 3
+ if (PyString_Check(obj))
+ {
+ int rc;
+ PyObject *uobj;
+
+ if ((uobj = PyUnicode_FromObject(obj)) == NULL)
+ return -1;
+
+ rc = convertToWCharString(uobj, ap);
+ Py_DECREF(uobj);
+
+ return rc;
+ }
+#endif
+
+ return -1;
+}
+
+
+/*
+ * Convert a Unicode object to a wide character string and return a copy on
+ * the heap.
+ */
+static int convertToWCharString(PyObject *obj, wchar_t **ap)
+{
+ SIP_SSIZE_T ulen;
+ wchar_t *wc;
+
+ ulen = PyUnicode_GET_SIZE(obj);
+
+ if ((wc = sip_api_malloc((ulen + 1) * sizeof (wchar_t))) == NULL)
+ return -1;
+
+ ulen = PyUnicode_AsWideChar((PyUnicodeObject *)obj, wc, ulen);
+
+ if (ulen < 0)
+ {
+ sip_api_free(wc);
+ return -1;
+ }
+
+ wc[ulen] = L'\0';
+
+ *ap = wc;
+
+ return 0;
+}
+
+#else
+
+/*
+ * Convert a Python object to a wide character.
+ */
+static int sip_api_unicode_as_wchar(PyObject *obj)
+{
+ raiseNoWChar();
+
+ return 0;
+}
+
+
+/*
+ * Convert a Python object to a wide character.
+ */
+static int *sip_api_unicode_as_wstring(PyObject *obj)
+{
+ raiseNoWChar();
+
+ return NULL;
+}
+
+
+/*
+ * Report the need for absent wide character support.
+ */
+static void raiseNoWChar()
+{
+ PyErr_SetString(PyExc_SystemError, "sip built without wchar_t support");
+}
+
+#endif
+
+
+/*
+ * The enum type alloc slot.
+ */
+static PyObject *sipEnumType_alloc(PyTypeObject *self, SIP_SSIZE_T nitems)
+{
+ sipEnumTypeObject *py_type;
+ sipPySlotDef *psd;
+
+ assert(currentType != NULL);
+
+ /* Call the standard super-metatype alloc. */
+ if ((py_type = (sipEnumTypeObject *)PyType_Type.tp_alloc(self, nitems)) == NULL)
+ return NULL;
+
+ /*
+ * Set the links between the Python type object and the generated type
+ * structure. Strictly speaking this doesn't need to be done here.
+ */
+ py_type->type = currentType;
+ currentType->u.td_py_type = (PyTypeObject *)py_type;
+
+ /*
+ * Initialise any slots. This must be done here, after the type is
+ * allocated but before PyType_Ready() is called.
+ */
+ if ((psd = ((sipEnumTypeDef *)currentType)->etd_pyslots) != NULL)
+ addTypeSlots(&py_type->super, psd);
+
+ currentType = NULL;
+
+ return (PyObject *)py_type;
+}
diff --git a/siplib/siplib.sbf b/siplib/siplib.sbf
new file mode 100644
index 0000000..79f9a45
--- /dev/null
+++ b/siplib/siplib.sbf
@@ -0,0 +1,19 @@
+# This is the build file for the extension module.
+#
+# Copyright (c) 2010 Riverbank Computing Limited <info@riverbankcomputing.com>
+#
+# This file is part of SIP.
+#
+# This copy of SIP is licensed for use under the terms of the SIP License
+# Agreement. See the file LICENSE for more details.
+#
+# This copy of SIP may also used under the terms of the GNU General Public
+# License v2 or v3 as published by the Free Software Foundation which can be
+# found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package.
+#
+# SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+target = sip
+sources = siplib.c apiversions.c descriptors.c qtlib.c threads.c objmap.c voidptr.c bool.cpp
+headers = sip.h sipint.h
diff --git a/siplib/threads.c b/siplib/threads.c
new file mode 100644
index 0000000..0854a0a
--- /dev/null
+++ b/siplib/threads.c
@@ -0,0 +1,226 @@
+/*
+ * Thread support for the SIP library. This module provides the hooks for
+ * C++ classes that provide a thread interface to interact properly with the
+ * Python threading infrastructure.
+ *
+ * Copyright (c) 2010 Riverbank Computing Limited <info@riverbankcomputing.com>
+ *
+ * This file is part of SIP.
+ *
+ * This copy of SIP is licensed for use under the terms of the SIP License
+ * Agreement. See the file LICENSE for more details.
+ *
+ * This copy of SIP may also used under the terms of the GNU General Public
+ * License v2 or v3 as published by the Free Software Foundation which can be
+ * found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package.
+ *
+ * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+#include "sip.h"
+#include "sipint.h"
+
+
+/*
+ * The data associated with pending request to wrap an object.
+ */
+typedef struct _pendingDef {
+ void *cpp; /* The C/C++ object ot be wrapped. */
+ sipWrapper *owner; /* The owner of the object. */
+ int flags; /* The flags. */
+} pendingDef;
+
+
+#ifdef WITH_THREAD
+
+#include <pythread.h>
+
+
+/*
+ * The per thread data we need to maintain.
+ */
+typedef struct _threadDef {
+ long thr_ident; /* The thread identifier. */
+ pendingDef pending; /* An object waiting to be wrapped. */
+ struct _threadDef *next; /* Next in the list. */
+} threadDef;
+
+
+static threadDef *threads = NULL; /* Linked list of threads. */
+
+
+static threadDef *currentThreadDef(void);
+
+#endif
+
+
+static pendingDef pending; /* An object waiting to be wrapped. */
+
+
+/*
+ * Get the address of any C/C++ object waiting to be wrapped.
+ */
+void *sipGetPending(sipWrapper **op, int *fp)
+{
+ pendingDef *pp;
+
+#ifdef WITH_THREAD
+ threadDef *thread;
+
+ if ((thread = currentThreadDef()) != NULL)
+ pp = &thread->pending;
+ else
+ pp = &pending;
+#else
+ pp = &pending;
+#endif
+
+ if (pp->cpp != NULL)
+ {
+ if (op != NULL)
+ *op = pp->owner;
+
+ if (fp != NULL)
+ *fp = pp->flags;
+ }
+
+ return pp->cpp;
+}
+
+
+/*
+ * Convert a new C/C++ pointer to a Python instance.
+ */
+PyObject *sipWrapSimpleInstance(void *cppPtr, const sipTypeDef *td,
+ sipWrapper *owner, int flags)
+{
+ static PyObject *nullargs = NULL;
+
+ pendingDef old_pending;
+ PyObject *self;
+#ifdef WITH_THREAD
+ threadDef *thread;
+#endif
+
+ if (nullargs == NULL && (nullargs = PyTuple_New(0)) == NULL)
+ return NULL;
+
+ if (cppPtr == NULL)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ /*
+ * Object creation can trigger the Python garbage collector which in turn
+ * can execute arbitrary Python code which can then call this function
+ * recursively. Therefore we save any existing pending object before
+ * setting the new one.
+ */
+#ifdef WITH_THREAD
+ if ((thread = currentThreadDef()) != NULL)
+ {
+ old_pending = thread->pending;
+
+ thread->pending.cpp = cppPtr;
+ thread->pending.owner = owner;
+ thread->pending.flags = flags;
+ }
+ else
+ {
+ old_pending = pending;
+
+ pending.cpp = cppPtr;
+ pending.owner = owner;
+ pending.flags = flags;
+ }
+#else
+ old_pending = pending;
+
+ pending.cpp = cppPtr;
+ pending.owner = owner;
+ pending.flags = flags;
+#endif
+
+ self = PyObject_Call((PyObject *)sipTypeAsPyTypeObject(td), nullargs, NULL);
+
+#ifdef WITH_THREAD
+ if (thread != NULL)
+ thread->pending = old_pending;
+ else
+ pending = old_pending;
+#else
+ pending = old_pending;
+#endif
+
+ return self;
+}
+
+
+/*
+ * This is called from a newly created thread to initialise some thread local
+ * storage.
+ */
+void sip_api_start_thread(void)
+{
+#ifdef WITH_THREAD
+ threadDef *thread;
+
+ /* Save the thread ID. First, find an empty slot in the list. */
+ for (thread = threads; thread != NULL; thread = thread->next)
+ if (thread->thr_ident == 0)
+ break;
+
+ if (thread == NULL)
+ {
+ thread = sip_api_malloc(sizeof (threadDef));
+ thread->next = threads;
+ threads = thread;
+ }
+
+ if (thread != NULL)
+ {
+ thread->thr_ident = PyThread_get_thread_ident();
+ thread->pending.cpp = NULL;
+ }
+#endif
+}
+
+
+/*
+ * Handle the termination of a thread. The thread state should already have
+ * been handled by the last call to PyGILState_Release().
+ */
+void sip_api_end_thread(void)
+{
+#ifdef WITH_THREAD
+ threadDef *thread;
+
+ /* We have the GIL at this point. */
+ if ((thread = currentThreadDef()) != NULL)
+ thread->thr_ident = 0;
+#endif
+}
+
+
+#ifdef WITH_THREAD
+
+/*
+ * Return the thread data for the current thread or NULL if it wasn't
+ * recognised.
+ */
+static threadDef *currentThreadDef(void)
+{
+ threadDef *thread;
+ long ident = PyThread_get_thread_ident();
+
+ for (thread = threads; thread != NULL; thread = thread->next)
+ if (thread->thr_ident == ident)
+ break;
+
+ return thread;
+}
+
+#endif
diff --git a/siplib/voidptr.c b/siplib/voidptr.c
new file mode 100644
index 0000000..fc26046
--- /dev/null
+++ b/siplib/voidptr.c
@@ -0,0 +1,579 @@
+/*
+ * SIP library code.
+ *
+ * Copyright (c) 2010 Riverbank Computing Limited <info@riverbankcomputing.com>
+ *
+ * This file is part of SIP.
+ *
+ * This copy of SIP is licensed for use under the terms of the SIP License
+ * Agreement. See the file LICENSE for more details.
+ *
+ * This copy of SIP may also used under the terms of the GNU General Public
+ * License v2 or v3 as published by the Free Software Foundation which can be
+ * found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package.
+ *
+ * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+#include <Python.h>
+
+#include <stddef.h>
+
+#include "sip.h"
+#include "sipint.h"
+
+
+/* The object data structure. */
+typedef struct {
+ PyObject_HEAD
+ void *voidptr;
+ SIP_SSIZE_T size;
+ int rw;
+} sipVoidPtrObject;
+
+
+/* The structure used to hold the results of a voidptr conversion. */
+struct vp_values {
+ void *voidptr;
+ SIP_SSIZE_T size;
+ int rw;
+};
+
+
+static PyObject *make_voidptr(void *voidptr, SIP_SSIZE_T size, int rw);
+static int vp_convertor(PyObject *arg, struct vp_values *vp);
+
+
+/*
+ * Implement __new__ for the type.
+ */
+static PyObject *sipVoidPtr_new(PyTypeObject *subtype, PyObject *args,
+ PyObject *kw)
+{
+ static char *kwlist[] = {"address", "size", "writeable", NULL};
+
+ struct vp_values vp_conversion;
+ SIP_SSIZE_T size = -1;
+ int rw = -1;
+ PyObject *obj;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kw,
+#if PY_VERSION_HEX >= 0x02050000
+ "O&|ni:voidptr",
+#else
+ "O&|ii:voidptr",
+#endif
+ kwlist, vp_convertor, &vp_conversion, &size, &rw))
+ return NULL;
+
+ /* Use the explicit size if one was given. */
+ if (size >= 0)
+ vp_conversion.size = size;
+
+ /* Use the explicit writeable flag if one was given. */
+ if (rw >= 0)
+ vp_conversion.rw = rw;
+
+ /* Create the instance. */
+ if ((obj = subtype->tp_alloc(subtype, 0)) == NULL)
+ return NULL;
+
+ /* Save the values. */
+ ((sipVoidPtrObject *)obj)->voidptr = vp_conversion.voidptr;
+ ((sipVoidPtrObject *)obj)->size = vp_conversion.size;
+ ((sipVoidPtrObject *)obj)->rw = vp_conversion.rw;
+
+ return obj;
+}
+
+
+#if PY_MAJOR_VERSION >= 3
+/*
+ * The read buffer implementation for Python v3.
+ */
+static int sipVoidPtr_getbuffer(PyObject *self, Py_buffer *buf, int flags)
+{
+ sipVoidPtrObject *v = (sipVoidPtrObject *)self;
+
+ return PyBuffer_FillInfo(buf, self, v->voidptr, v->size, !v->rw, flags);
+}
+#endif
+
+
+#if PY_MAJOR_VERSION < 3
+/*
+ * The read buffer implementation for Python v2.
+ */
+static SIP_SSIZE_T sipVoidPtr_getbuffer(PyObject *self, SIP_SSIZE_T seg,
+ void **ptr)
+{
+ SIP_SSIZE_T size = ((sipVoidPtrObject *)self)->size;
+
+ if (size < 0 || seg != 0)
+ {
+ PyErr_SetString(PyExc_SystemError, "invalid buffer segment");
+ return -1;
+ }
+
+ *ptr = ((sipVoidPtrObject *)self)->voidptr;
+
+ return size;
+}
+#endif
+
+
+#if PY_MAJOR_VERSION < 3
+/*
+ * The write buffer implementation for Python v2.
+ */
+static SIP_SSIZE_T sipVoidPtr_getwritebuffer(PyObject *self, SIP_SSIZE_T seg,
+ void **ptr)
+{
+ if (((sipVoidPtrObject *)self)->rw)
+ return sipVoidPtr_getbuffer(self, seg, ptr);
+
+ PyErr_SetString(PyExc_TypeError, "the sip.voidptr is not writeable");
+ return -1;
+}
+#endif
+
+
+#if PY_MAJOR_VERSION < 3
+/*
+ * The segment count implementation for Python v2.
+ */
+static SIP_SSIZE_T sipVoidPtr_getsegcount(PyObject *self, SIP_SSIZE_T *lenp)
+{
+ SIP_SSIZE_T segs, len;
+
+ len = ((sipVoidPtrObject *)self)->size;
+ segs = (len < 0 ? 0 : 1);
+
+ if (lenp != NULL)
+ *lenp = len;
+
+ return segs;
+}
+#endif
+
+
+/*
+ * Implement int() for the type.
+ */
+static PyObject *sipVoidPtr_int(sipVoidPtrObject *v)
+{
+ return PyLong_FromVoidPtr(v->voidptr);
+}
+
+
+#if PY_MAJOR_VERSION < 3
+/*
+ * Implement hex() for the type.
+ */
+static PyObject *sipVoidPtr_hex(sipVoidPtrObject *v)
+{
+ char buf[2 + 16 + 1];
+
+ PyOS_snprintf(buf, sizeof (buf), "0x%.*lx", (int)(sizeof (void *) * 2),
+ (unsigned long)v->voidptr);
+
+ return PyString_FromString(buf);
+}
+#endif
+
+
+#if defined(SIP_USE_PYCAPSULE)
+/*
+ * Implement ascapsule() for the type.
+ */
+static PyObject *sipVoidPtr_ascapsule(sipVoidPtrObject *v, PyObject *arg)
+{
+ return PyCapsule_New(v->voidptr, NULL, NULL);
+}
+#endif
+
+
+/*
+ * Implement ascobject() for the type.
+ */
+static PyObject *sipVoidPtr_ascobject(sipVoidPtrObject *v, PyObject *arg)
+{
+ return PyCObject_FromVoidPtr(v->voidptr, NULL);
+}
+
+
+/*
+ * Implement asstring() for the type.
+ */
+static PyObject *sipVoidPtr_asstring(sipVoidPtrObject *v, PyObject *args,
+ PyObject *kw)
+{
+ static char *kwlist[] = {"size", NULL};
+
+ SIP_SSIZE_T size = -1;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kw,
+#if PY_VERSION_HEX >= 0x02050000
+ "|n:asstring",
+#else
+ "|i:asstring",
+#endif
+ kwlist, &size))
+ return NULL;
+
+ /* Use the current size if one wasn't explicitly given. */
+ if (size < 0)
+ size = v->size;
+
+ if (size < 0)
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "a size must be given or the sip.voidptr must have a size");
+ return NULL;
+ }
+
+ return SIPBytes_FromStringAndSize(v->voidptr, size);
+}
+
+
+/*
+ * Implement getsize() for the type.
+ */
+static PyObject *sipVoidPtr_getsize(sipVoidPtrObject *v, PyObject *arg)
+{
+#if PY_MAJOR_VERSION >= 3
+ return PyLong_FromSsize_t(v->size);
+#elif PY_VERSION_HEX >= 0x02050000
+ return PyInt_FromSsize_t(v->size);
+#else
+ return PyInt_FromLong(v->size);
+#endif
+}
+
+
+/*
+ * Implement setsize() for the type.
+ */
+static PyObject *sipVoidPtr_setsize(sipVoidPtrObject *v, PyObject *arg)
+{
+ SIP_SSIZE_T size;
+
+#if PY_MAJOR_VERSION >= 3
+ size = PyLong_AsSsize_t(arg);
+#elif PY_VERSION_HEX >= 0x02050000
+ size = PyInt_AsSsize_t(arg);
+#else
+ size = (int)PyInt_AsLong(arg);
+#endif
+
+ if (PyErr_Occurred())
+ return NULL;
+
+ v->size = size;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+/*
+ * Implement getwriteable() for the type.
+ */
+static PyObject *sipVoidPtr_getwriteable(sipVoidPtrObject *v, PyObject *arg)
+{
+ return PyBool_FromLong(v->rw);
+}
+
+
+/*
+ * Implement setwriteable() for the type.
+ */
+static PyObject *sipVoidPtr_setwriteable(sipVoidPtrObject *v, PyObject *arg)
+{
+ int rw;
+
+ rw = (int)SIPLong_AsLong(arg);
+
+ if (PyErr_Occurred())
+ return NULL;
+
+ v->rw = rw;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+/* The methods data structure. */
+static PyMethodDef sipVoidPtr_Methods[] = {
+#if defined(SIP_USE_PYCAPSULE)
+ {"ascapsule", (PyCFunction)sipVoidPtr_ascapsule, METH_NOARGS, NULL},
+#endif
+ {"ascobject", (PyCFunction)sipVoidPtr_ascobject, METH_NOARGS, NULL},
+ {"asstring", (PyCFunction)sipVoidPtr_asstring, METH_KEYWORDS, NULL},
+ {"getsize", (PyCFunction)sipVoidPtr_getsize, METH_NOARGS, NULL},
+ {"setsize", (PyCFunction)sipVoidPtr_setsize, METH_O, NULL},
+ {"getwriteable", (PyCFunction)sipVoidPtr_getwriteable, METH_NOARGS, NULL},
+ {"setwriteable", (PyCFunction)sipVoidPtr_setwriteable, METH_O, NULL},
+ {NULL}
+};
+
+
+/* The number methods data structure. */
+static PyNumberMethods sipVoidPtr_NumberMethods = {
+ 0, /* nb_add */
+ 0, /* nb_subtract */
+ 0, /* nb_multiply */
+#if PY_MAJOR_VERSION < 3
+ 0, /* nb_divide */
+#endif
+ 0, /* nb_remainder */
+ 0, /* nb_divmod */
+ 0, /* nb_power */
+ 0, /* nb_negative */
+ 0, /* nb_positive */
+ 0, /* nb_absolute */
+ 0, /* nb_bool (Python v3), nb_nonzero (Python v2) */
+ 0, /* nb_invert */
+ 0, /* nb_lshift */
+ 0, /* nb_rshift */
+ 0, /* nb_and */
+ 0, /* nb_xor */
+ 0, /* nb_or */
+#if PY_MAJOR_VERSION < 3
+ 0, /* nb_coerce */
+#endif
+ (unaryfunc)sipVoidPtr_int, /* nb_int */
+ 0, /* nb_reserved (Python v3), nb_long (Python v2) */
+ 0, /* nb_float */
+#if PY_MAJOR_VERSION < 3
+ 0, /* nb_oct */
+ (unaryfunc)sipVoidPtr_hex, /* nb_hex */
+#endif
+ 0, /* nb_inplace_add */
+ 0, /* nb_inplace_subtract */
+ 0, /* nb_inplace_multiply */
+#if PY_MAJOR_VERSION < 3
+ 0, /* nb_inplace_divide */
+#endif
+ 0, /* nb_inplace_remainder */
+ 0, /* nb_inplace_power */
+ 0, /* nb_inplace_lshift */
+ 0, /* nb_inplace_rshift */
+ 0, /* nb_inplace_and */
+ 0, /* nb_inplace_xor */
+ 0, /* nb_inplace_or */
+ 0, /* nb_floor_divide */
+ 0, /* nb_true_divide */
+ 0, /* nb_inplace_floor_divide */
+ 0, /* nb_inplace_true_divide */
+#if PY_VERSION_HEX >= 0x02050000
+ 0 /* nb_index */
+#endif
+};
+
+
+/* The buffer methods data structure. */
+static PyBufferProcs sipVoidPtr_BufferProcs = {
+ sipVoidPtr_getbuffer,
+#if PY_MAJOR_VERSION >= 3
+ NULL,
+#else
+ sipVoidPtr_getwritebuffer,
+ sipVoidPtr_getsegcount,
+#if PY_VERSION_HEX >= 0x02050000
+ (charbufferproc)sipVoidPtr_getbuffer
+#else
+ (getcharbufferproc)sipVoidPtr_getbuffer
+#endif
+#endif
+};
+
+
+/* The type data structure. */
+PyTypeObject sipVoidPtr_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "sip.voidptr", /* tp_name */
+ sizeof (sipVoidPtrObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved (Python v3), tp_compare (Python v2) */
+ 0, /* tp_repr */
+ &sipVoidPtr_NumberMethods, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ &sipVoidPtr_BufferProcs, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ sipVoidPtr_Methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ sipVoidPtr_new, /* tp_new */
+};
+
+
+/*
+ * A convenience function to convert a C/C++ void pointer from a Python object.
+ */
+void *sip_api_convert_to_void_ptr(PyObject *obj)
+{
+ if (obj == NULL)
+ {
+ PyErr_SetString(PyExc_TypeError, "sip.voidptr is NULL");
+ return NULL;
+ }
+
+ if (obj == Py_None)
+ return NULL;
+
+ if (PyObject_TypeCheck(obj, &sipVoidPtr_Type))
+ return ((sipVoidPtrObject *)obj)->voidptr;
+
+#if defined(SIP_USE_PYCAPSULE)
+ if (PyCapsule_CheckExact(obj))
+ return PyCapsule_GetPointer(obj, NULL);
+#endif
+
+ if (PyCObject_Check(obj))
+ return PyCObject_AsVoidPtr(obj);
+
+#if PY_MAJOR_VERSION >= 3
+ return PyLong_AsVoidPtr(obj);
+#else
+ return (void *)PyInt_AsLong(obj);
+#endif
+}
+
+
+/*
+ * Convert a C/C++ void pointer to a sip.voidptr object.
+ */
+PyObject *sip_api_convert_from_void_ptr(void *val)
+{
+ return make_voidptr(val, -1, TRUE);
+}
+
+
+/*
+ * Convert a C/C++ void pointer to a sip.voidptr object.
+ */
+PyObject *sip_api_convert_from_const_void_ptr(const void *val)
+{
+ return make_voidptr((void *)val, -1, FALSE);
+}
+
+
+/*
+ * Convert a sized C/C++ void pointer to a sip.voidptr object.
+ */
+PyObject *sip_api_convert_from_void_ptr_and_size(void *val, SIP_SSIZE_T size)
+{
+ return make_voidptr(val, size, TRUE);
+}
+
+
+/*
+ * Convert a sized C/C++ const void pointer to a sip.voidptr object.
+ */
+PyObject *sip_api_convert_from_const_void_ptr_and_size(const void *val,
+ SIP_SSIZE_T size)
+{
+ return make_voidptr((void *)val, size, FALSE);
+}
+
+
+/*
+ * Do the work of converting a void pointer.
+ */
+static PyObject *make_voidptr(void *voidptr, SIP_SSIZE_T size, int rw)
+{
+ sipVoidPtrObject *self;
+
+ if (voidptr == NULL)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ if ((self = PyObject_NEW(sipVoidPtrObject, &sipVoidPtr_Type)) == NULL)
+ return NULL;
+
+ self->voidptr = voidptr;
+ self->size = size;
+ self->rw = rw;
+
+ return (PyObject *)self;
+}
+
+
+/*
+ * Convert a Python object to the values needed to create a voidptr.
+ */
+static int vp_convertor(PyObject *arg, struct vp_values *vp)
+{
+ void *ptr;
+ SIP_SSIZE_T size = -1;
+ int rw = TRUE;
+
+ if (arg == Py_None)
+ ptr = NULL;
+#if defined(SIP_USE_PYCAPSULE)
+ else if (PyCapsule_CheckExact(arg))
+ ptr = PyCapsule_GetPointer(arg, NULL);
+#endif
+ else if (PyCObject_Check(arg))
+ ptr = PyCObject_AsVoidPtr(arg);
+ else if (PyObject_TypeCheck(arg, &sipVoidPtr_Type))
+ {
+ ptr = ((sipVoidPtrObject *)arg)->voidptr;
+ size = ((sipVoidPtrObject *)arg)->size;
+ rw = ((sipVoidPtrObject *)arg)->rw;
+ }
+ else
+ {
+#if PY_MAJOR_VERSION >= 3
+ ptr = PyLong_AsVoidPtr(arg);
+#else
+ ptr = (void *)PyInt_AsLong(arg);
+#endif
+
+ if (PyErr_Occurred())
+ {
+#if PY_VERSION_HEX >= 0x03010000
+ PyErr_SetString(PyExc_TypeError, "a single integer, CObject, None or another voidptr is required");
+#else
+ PyErr_SetString(PyExc_TypeError, "a single integer, Capsule, CObject, None or another voidptr is required");
+#endif
+ return 0;
+ }
+ }
+
+ vp->voidptr = ptr;
+ vp->size = size;
+ vp->rw = rw;
+
+ return 1;
+}