diff options
Diffstat (limited to 'python/sip/siplib')
-rw-r--r-- | python/sip/siplib/bool.cpp | 19 | ||||
-rw-r--r-- | python/sip/siplib/objmap.c | 264 | ||||
-rw-r--r-- | python/sip/siplib/qtlib.c | 1254 | ||||
-rw-r--r-- | python/sip/siplib/sip.h | 1302 | ||||
-rw-r--r-- | python/sip/siplib/sipint.h | 121 | ||||
-rw-r--r-- | python/sip/siplib/siplib.c | 7902 | ||||
-rw-r--r-- | python/sip/siplib/siplib.sbf | 16 | ||||
-rw-r--r-- | python/sip/siplib/threads.c | 223 |
8 files changed, 0 insertions, 11101 deletions
diff --git a/python/sip/siplib/bool.cpp b/python/sip/siplib/bool.cpp deleted file mode 100644 index c21a0c79..00000000 --- a/python/sip/siplib/bool.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// This contains all the C++ code that is needed by the sip module. -// -// Copyright (c) 2007 -// Riverbank Computing Limited <info@riverbankcomputing.co.uk> -// -// 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. -// -// 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/python/sip/siplib/objmap.c b/python/sip/siplib/objmap.c deleted file mode 100644 index efc7bc2a..00000000 --- a/python/sip/siplib/objmap.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * This module implements a hash table class for mapping C/C++ addresses to the - * corresponding wrapped Python object. - * - * Copyright (c) 2007 - * Riverbank Computing Limited <info@riverbankcomputing.co.uk> - * - * 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. - * - * 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. - */ -sipWrapper *sipOMFindObject(sipObjectMap *om,void *key, sipWrapperType *type) -{ - sipHashEntry *he = findHashEntry(om, key); - sipWrapper *w; - - /* Go through each wrapped object at this address. */ - for (w = he->first; w != NULL; w = w->next) - { - /* - * If this wrapped object is of the given type, or a sub-type - * of it, or vice versa, then we assume it is the same C++ - * object. - */ - if (PyObject_TypeCheck(w, (PyTypeObject *)type) || - PyType_IsSubtype((PyTypeObject *)type, w->ob_type)) - return w; - } - - return NULL; -} - - -/* - * Add a C/C++ address and the corresponding wrapped Python object to the map. - */ -void sipOMAddObject(sipObjectMap *om,sipWrapper *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)) - { - sipWrapper *w; - - for (w = he -> first; w != NULL; w = w -> next) - w -> u.cppPtr = NULL; - - he -> first = NULL; - } - - 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,sipWrapper *val) -{ - sipHashEntry *he = findHashEntry(om,val -> u.cppPtr); - sipWrapper **wp; - - for (wp = &he -> first; *wp != NULL; wp = &(*wp) -> next) - if (*wp == val) - { - *wp = 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/python/sip/siplib/qtlib.c b/python/sip/siplib/qtlib.c deleted file mode 100644 index f3ba4301..00000000 --- a/python/sip/siplib/qtlib.c +++ /dev/null @@ -1,1254 +0,0 @@ -/* - * The SIP library code that implements the interface to the optional module - * supplied Qt support. - * - * Copyright (c) 2007 - * Riverbank Computing Limited <info@riverbankcomputing.co.uk> - * - * 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. - * - * 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" - - -/* This is how Qt "types" signals and slots. */ -#define isQtSlot(s) (*(s) == '1') -#define isQtSignal(s) (*(s) == '2') - - -static PyObject *py_sender = NULL; /* The last Python signal sender. */ - - -static int isSameSlot(sipSlot *,PyObject *,const char *); -static int emitQtSig(sipWrapper *,const char *,PyObject *); -static int emitToSlotList(sipSlotList *rxlist, PyObject *sigargs); -static int addSlotToPySigList(sipWrapper *,const char *,PyObject *,const char *); -static void removeSlotFromPySigList(sipWrapper *,const char *,PyObject *,const char *); -static PyObject *getWeakRef(PyObject *obj); -static sipPySig *findPySignal(sipWrapper *,const char *); -static char *sipStrdup(const char *); -static int saveSlot(sipSlot *sp, PyObject *rxObj, const char *slot); -static void *createUniversalSlot(sipWrapper *txSelf, const char *sig, PyObject *rxObj, const char *slot, const char **member); -static void *findSignal(void *txrx, const char **sig); -static void *newSignal(void *txrx, const char **sig); -static void freeSlot(sipSlot *slot); - - -/* - * Return the most recent signal sender. - */ -PyObject *sip_api_get_sender() -{ - PyObject *sender; - const void *qt_sender; - - /* - * If there is a Qt sender then it is more recent than the last Python - * sender, so use it instead. - */ - if ((qt_sender = sipQtSupport->qt_get_sender()) != NULL) - sender = sip_api_convert_from_instance((void *)qt_sender, sipQObjectClass, NULL); - else - { - if ((sender = py_sender) == NULL) - sender = Py_None; - - Py_INCREF(sender); - } - - return sender; -} - - -/* - * Release the resources held by a connection. - */ -void sip_api_free_connection(sipSlotConnection *conn) -{ - freeSlot(&conn->sc_slot); -} - - -/* - * Compare two connections and return TRUE if they are the same. - */ -int sip_api_same_connection(sipSlotConnection *conn, void *tx, const char *sig, - PyObject *rxObj, const char *slot) -{ - return (conn->sc_transmitter == tx && - sipQtSupport->qt_same_name(conn->sc_signature->sg_signature, sig) && - isSameSlot(&conn->sc_slot, rxObj, slot)); -} - - -/* - * Parse the signal arguments for a connection. - */ -sipSignature *sip_api_parse_signature(const char *sig) -{ - static sipSignature *psig_list = NULL; - sipSignature *psig; - const char *sp, *ep; - - /* - * First see if it has already been parsed. Note that both sides of a - * connection will probably be parsed twice because the function names will - * be different even though the signatures will probably be the same. We - * could be more clever, the most saving is when repeatedly emitting a - * signal for which this is sufficient. - */ - for (psig = psig_list; psig != NULL; psig = psig->sg_next) - if (sipQtSupport->qt_same_name(psig->sg_signature, sig)) - return psig; - - /* Create a new one including space for the copy of the signature. */ - if ((psig = (sipSignature *)sip_api_malloc(sizeof (sipSignature) + strlen(sig) + 1)) == NULL) - return NULL; - - psig->sg_signature = (char *)&psig[1]; - psig->sg_nrargs = 0; - psig->sg_args = 0; - - /* Find the start and end of the arguments. */ - sp = strchr(sig, '('); - ep = strrchr(sig, ')'); - - /* If the signal isn't well formed we assume Qt will pick it up. */ - if (sp && ep && sp < ep) - { - /* - * Copy the signature arguments while counting them and - * removing non-significant spaces. Each argument is left as a - * '\0' terminated string. - */ - char *dp = psig->sg_signature; - int depth = 0, nrcommas = 0, argstart = TRUE; - - for (;;) - { - char ch = *++sp; - - if (strchr(",*&)<>", ch)) - { - /* Backup over any previous trailing space. */ - if (dp > psig->sg_signature && dp[-1] == ' ') - --dp; - - if (sp == ep) - { - *dp = '\0'; - break; - } - - if (ch == ',' && depth == 0) - { - *dp++ = '\0'; - ++nrcommas; - argstart = TRUE; - } - else - { - *dp++ = ch; - - /* - * Make sure commas in template - * arguments are ignored. - */ - if (ch == '<') - ++depth; - else if (ch == '>') - --depth; - } - } - else if (ch == ' ') - { - /* Ignore leading and multiple spaces. */ - if (!argstart && dp[-1] != ' ') - *dp++ = ch; - } - else - { - *dp++ = ch; - argstart = FALSE; - } - } - - /* Handle the arguments now they are in a normal form. */ - if (*psig->sg_signature) - { - char *arg = psig->sg_signature; - int a; - - /* Allocate the space. */ - psig->sg_nrargs = nrcommas + 1; - - if ((psig->sg_args = (sipSigArg *)sip_api_malloc(sizeof (sipSigArg) * psig->sg_nrargs)) == NULL) - { - sip_api_free(psig); - return NULL; - } - - for (a = 0; a < psig->sg_nrargs; ++a) - { - size_t btlen = 0; - int unsup, isref = FALSE, indir = 0; - sipSigArgType sat = unknown_sat; - - /* Find the start of the significant part of the type. */ - dp = arg; - - if (strncmp(dp, "const ", 6) == 0) - dp += 6; - - /* - * Find the length of the base type, the number of indirections - * and if it is a reference. - */ - for (ep = dp; *ep; ++ep) - if (*ep == '&') - isref = TRUE; - else if (*ep == '*') - ++indir; - else - ++btlen; - - /* - * Assume that anything other than a base type is unsupported. - */ - unsup = (isref || indir); - - /* Parse the base type. */ - switch (btlen) - { - case 3: - if (strncmp(dp, "int", 3) == 0) - sat = int_sat; - break; - - case 4: - if (strncmp(dp, "bool", 4) == 0) - sat = bool_sat; - else if (strncmp(dp, "long", 4) == 0) - sat = long_sat; - else if (strncmp(dp, "char", 4) == 0) - { - sat = (indir ? string_sat : char_sat); - unsup = (isref || indir > 1); - } - else if (strncmp(dp, "void", 4) == 0) - { - sat = void_sat; - unsup = (isref || indir != 1); - } - break; - - case 5: - if (strncmp(dp, "float", 5) == 0) - sat = float_sat; - else if (strncmp(dp, "short", 5) == 0) - sat = short_sat; - break; - - case 6: - if (strncmp(dp, "double", 6) == 0) - sat = double_sat; - break; - - case 7: - if (strncmp(dp, "__int64", 7) == 0) - sat = longlong_sat; - else if (strncmp(dp, "wchar_t", 7) == 0) - { - sat = (indir ? wstring_sat : wchar_sat); - unsup = (isref || indir > 1); - } - break; - - case 8: - if (strncmp(dp, "unsigned", 8) == 0) - sat = uint_sat; - else if (strncmp(dp, "TQVariant", 8) == 0) - { - if (indir == 0) - { - sat = qvariant_sat; - unsup = FALSE; - } - else if (indir == 1) - { - sat = qvariantp_sat; - unsup = FALSE; - } - } - break; - - case 9: - if (strncmp(dp, "long long", 9) == 0) - sat = longlong_sat; - break; - - case 11: - if (strncmp(dp, "signed char", 11) == 0) - { - sat = (indir ? sstring_sat : schar_sat); - unsup = (isref || indir > 1); - } - break; - - case 12: - if (strncmp(dp, "unsigned int", 12) == 0) - sat = uint_sat; - break; - - case 13: - if (strncmp(dp, "unsigned long", 13) == 0) - sat = ulong_sat; - else if (strncmp(dp, "unsigned char", 13) == 0) - { - sat = (indir ? ustring_sat : uchar_sat); - unsup = (isref || indir > 1); - } - else if (strncmp(dp, "PyQt_PyObject", 13) == 0 && indir == 0) - { - sat = pyobject_sat; - unsup = FALSE; - } - break; - - case 14: - if (strncmp(dp, "unsigned short", 14) == 0) - sat = ushort_sat; - break; - - case 16: - if (strncmp(dp, "unsigned __int64", 16) == 0) - sat = ulonglong_sat; - break; - - case 18: - if (strncmp(dp, "unsigned long long", 18) == 0) - sat = ulonglong_sat; - break; - } - - if (sat == unknown_sat) - sipFindSigArgType(dp, btlen, &psig->sg_args[a], indir); - else - { - if (unsup) - sat = unknown_sat; - - psig->sg_args[a].atype = sat; - } - - /* Move to the start of the next argument. */ - arg += strlen(arg) + 1; - } - } - } - - /* Make a deep copy of the signal. */ - strcpy(psig->sg_signature, sig); - - /* Add it to the list so it can be re-used. */ - psig->sg_next = psig_list; - psig_list = psig; - - return psig; -} - - -/* - * Find an existing signal. - */ -static void *findSignal(void *txrx, const char **sig) -{ - sipSignature *psig; - - /* - * Handle the trivial case where the Qt implementation doesn't support - * universal signals. - */ - if (sipQtSupport->qt_is_qt_signal == NULL) - return txrx; - - /* See if this a shortcircuited Python signal. */ - if (strchr(*sig, '(') == NULL) - return sipQtSupport->qt_find_universal_signal_shortcut(txrx, *sig, sig); - - /* See if the existing object can be used itself. */ - if (sipQtSupport->qt_is_qt_signal(txrx, *sig)) - return txrx; - - if ((psig = sip_api_parse_signature(*sig)) == NULL) - return NULL; - - /* Find an ordinary universal signal. */ - return sipQtSupport->qt_find_universal_signal(txrx, psig); -} - - -/* - * Return a usable signal, creating a new universal signal if needed. - */ -static void *newSignal(void *txrx, const char **sig) -{ - sipSignature *psig; - - /* - * Handle the trivial case where the Qt implementation doesn't support - * universal signals. - */ - if (sipQtSupport->qt_is_qt_signal == NULL) - return txrx; - - /* See if this a shortcircuited Python signal. */ - if (strchr(*sig, '(') == NULL) - return sipQtSupport->qt_create_universal_signal_shortcut(txrx, *sig, sig); - - /* See if the existing object can be used itself. */ - if (sipQtSupport->qt_is_qt_signal(txrx, *sig)) - return txrx; - - if ((psig = sip_api_parse_signature(*sig)) == NULL) - return NULL; - - /* Create an ordinary universal signal. */ - return sipQtSupport->qt_create_universal_signal(txrx, psig); -} - - -/* - * 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) -{ - sipSlotConnection conn; - void *us; - - /* Initialise the connection. */ - conn.sc_transmitter = (txSelf ? sipGetAddress(txSelf) : 0); - - /* Save the real slot. */ - if (saveSlot(&conn.sc_slot, rxObj, slot) < 0) - return 0; - - /* Parse the signature and create the universal slot. */ - if ((conn.sc_signature = sip_api_parse_signature(sig)) == NULL || (us = sipQtSupport->qt_create_universal_slot(txSelf, &conn, member)) == NULL) - { - sip_api_free_connection(&conn); - return 0; - } - - return us; -} - - -/* - * Emit a Python or Qt signal. - */ -int sip_api_emit_signal(PyObject *self,const char *sig,PyObject *sigargs) -{ - sipPySig *ps; - void *tx; - sipWrapper *w = (sipWrapper *)self; - - /* - * Don't do anything if signals are blocked. Qt signals would be blocked - * anyway, but this blocks Python signals as well. - */ - if ((tx = sip_api_get_cpp_ptr(w, sipQObjectClass)) == NULL || sipQtSupport->qt_signals_blocked(tx)) - return 0; - - if (isQtSignal(sig)) - { - sipSignature *psig; - - /* Handle Qt implementations that emit using generated code. */ - if (!sipQtSupport->qt_emit_signal) - return emitQtSig(w, sig, sigargs); - - /* See if the signal is a shortcut. */ - if (strchr(sig, '(') == NULL) - return sipQtSupport->qt_emit_signal_shortcut(tx, sig, sigargs); - - if ((psig = sip_api_parse_signature(sig)) == NULL) - return -1; - - if (psig->sg_nrargs != PyTuple_GET_SIZE(sigargs)) - PyErr_Format(PyExc_TypeError, "Signal has %d arguments, but %d given", psig->sg_nrargs, PyTuple_GET_SIZE(sigargs)); - - return sipQtSupport->qt_emit_signal(tx, psig, sigargs); - } - - if ((ps = findPySignal(w,sig)) != NULL) - { - int rc; - - /* Forget the last Qt sender and remember this one. */ - sipQtSupport->qt_forget_sender(); - py_sender = self; - - rc = emitToSlotList(ps -> rxlist,sigargs); - - /* Forget this as a sender. */ - py_sender = NULL; - - return rc; - } - - return 0; -} - - -/* - * Search the Python signal list for a signal. - */ -static sipPySig *findPySignal(sipWrapper *w,const char *sig) -{ - sipPySig *ps; - - for (ps = w -> pySigList; ps != NULL; ps = ps -> next) - if (sipQtSupport->qt_same_name(ps -> name,sig)) - return ps; - - return NULL; -} - - -/* - * Search a signal table for a signal. If found, call the emitter function - * with the signal arguments. Return 0 if the signal was emitted or <0 if - * there was an error. - */ -static int emitQtSig(sipWrapper *w,const char *sig,PyObject *sigargs) -{ - sipQtSignal *tab; - - /* Search the table. */ - for (tab = ((sipWrapperType *)(w -> ob_type)) -> type -> td_emit; tab -> st_name != NULL; ++tab) - { - const char *sp, *tp; - int found; - - /* Compare only the base name. */ - sp = &sig[1]; - tp = tab -> st_name; - - found = TRUE; - - while (*sp != '\0' && *sp != '(' && *tp != '\0') - if (*sp++ != *tp++) - { - found = FALSE; - break; - } - - if (found) - return (*tab -> st_emitfunc)(w,sigargs); - } - - /* It wasn't found if we got this far. */ - PyErr_Format(PyExc_NameError,"Invalid signal %s",&sig[1]); - - return -1; -} - - -/* - * Send a signal to a single slot (Qt or Python). - */ -int sip_api_emit_to_slot(sipSlot *slot, PyObject *sigargs) -{ - PyObject *sa, *oxtype, *oxvalue, *oxtb, *sfunc, *newmeth, *sref; - - /* Keep some compilers quiet. */ - oxtype = oxvalue = oxtb = NULL; - - /* Fan out Qt signals. */ - if (slot -> name != NULL && slot -> name[0] != '\0') - return sip_api_emit_signal(slot -> pyobj,slot -> name,sigargs); - - /* Get the object to call, resolving any weak references. */ - if (slot -> weakSlot == NULL) - sref = NULL; - else if ((sref = PyWeakref_GetObject(slot -> weakSlot)) == NULL) - return -1; - 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); - return 0; - } - - if (slot -> pyobj == NULL) - { - PyObject *self = (sref != NULL ? sref : slot->meth.mself); - - /* See if any underlying C++ instance has gone. */ - if (self != NULL && sip_api_wrapper_check(self) && ((sipWrapper *)self)->u.cppPtr == NULL) - { - Py_XDECREF(sref); - return 0; - } - - if ((sfunc = PyMethod_New(slot->meth.mfunc, self, slot->meth.mclass)) == NULL) - { - Py_XDECREF(sref); - return -1; - } - - /* Make sure we garbage collect the new method. */ - newmeth = sfunc; - } - else if (slot -> name != NULL) - { - char *mname = slot -> name + 1; - PyObject *self = (sref != NULL ? sref : slot->pyobj); - - /* See if any underlying C++ instance has gone. */ - if (self != NULL && sip_api_wrapper_check(self) && ((sipWrapper *)self)->u.cppPtr == NULL) - { - Py_XDECREF(sref); - return 0; - } - - 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(sref); - return -1; - } - - /* Make sure we garbage collect the new method. */ - newmeth = sfunc; - } - else if (slot->pyobj == Py_None) - { - /* - * This was a lambda function that has been freed by the cyclic garbage - * collector so ignore it. - */ - Py_XDECREF(sref); - return 0; - } - else - { - sfunc = slot -> pyobj; - newmeth = NULL; - } - - /* - * 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(resobj); - - Py_XDECREF(newmeth); - 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 0; - } - - /* 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_XDECREF(newmeth); - Py_XDECREF(sref); - - Py_DECREF(sa); - - return -1; -} - - -/* - * Send a signal to the slots (Qt or Python) in a Python list. - */ -static int emitToSlotList(sipSlotList *rxlist,PyObject *sigargs) -{ - int rc; - - /* Apply the arguments to each slot method. */ - rc = 0; - - while (rxlist != NULL && rc >= 0) - { - sipSlotList *next; - - /* - * We get the next in the list before calling the slot in case the list - * gets changed by the slot - usually because the slot disconnects - * itself. - */ - next = rxlist -> next; - rc = sip_api_emit_to_slot(&rxlist -> rx, sigargs); - rxlist = next; - } - - return rc; -} - - -/* - * Add a slot to a transmitter's Python signal list. The signal is a Python - * signal, the slot may be either a Qt signal, a Qt slot, a Python signal or a - * Python slot. - */ -static int addSlotToPySigList(sipWrapper *txSelf,const char *sig, - PyObject *rxObj,const char *slot) -{ - sipPySig *ps; - sipSlotList *psrx; - - /* Create a new one if necessary. */ - if ((ps = findPySignal(txSelf,sig)) == NULL) - { - if ((ps = (sipPySig *)sip_api_malloc(sizeof (sipPySig))) == NULL) - return -1; - - if ((ps -> name = sipStrdup(sig)) == NULL) - { - sip_api_free(ps); - return -1; - } - - ps -> rxlist = NULL; - ps -> next = txSelf -> pySigList; - - txSelf -> pySigList = ps; - } - - /* Create the new receiver. */ - if ((psrx = (sipSlotList *)sip_api_malloc(sizeof (sipSlotList))) == NULL) - return -1; - - if (saveSlot(&psrx->rx, rxObj, slot) < 0) - { - sip_api_free(psrx); - return -1; - } - - psrx -> next = ps -> rxlist; - ps -> rxlist = psrx; - - return 0; -} - - -/* - * Compare two slots to see if they are the same. - */ -static int isSameSlot(sipSlot *slot1,PyObject *rxobj2,const char *slot2) -{ - /* See if they are signals or Qt slots, ie. they have a name. */ - if (slot1 -> name != NULL) - return (slot2 != NULL && - sipQtSupport->qt_same_name(slot1 -> name,slot2) && - slot1 -> pyobj == rxobj2); - - /* Both must be Python slots. */ - if (slot2 != NULL) - return 0; - - /* See if they are Python methods. */ - if (slot1 -> pyobj == NULL) - return (PyMethod_Check(rxobj2) && - slot1 -> meth.mfunc == PyMethod_GET_FUNCTION(rxobj2) && - slot1 -> meth.mself == PyMethod_GET_SELF(rxobj2) && - slot1 -> meth.mclass == PyMethod_GET_CLASS(rxobj2)); - - if (PyMethod_Check(rxobj2)) - return 0; - - /* The objects must be the same. */ - return (slot1 -> pyobj == rxobj2); -} - - -/* - * Convert a valid Python signal or slot to an existing universal slot. - */ -void *sipGetRx(sipWrapper *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((sipWrapper *)rxObj, sipQObjectClass)) == 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 *sig,PyObject *rxObj, - const char *slot,const char **memberp) -{ - if (slot == NULL) - return createUniversalSlot(txSelf, sig, rxObj, NULL, memberp); - - if (isQtSlot(slot) || isQtSignal(slot)) - { - void *rx; - - *memberp = slot; - - if ((rx = sip_api_get_cpp_ptr((sipWrapper *)rxObj, sipQObjectClass)) == 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, sig, rxObj, slot, memberp); -} - - -/* - * 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) -{ - sipWrapper *txSelf = (sipWrapper *)txObj; - - /* Handle Qt signals. */ - if (isQtSignal(sig)) - { - void *tx, *rx; - const char *member, *real_sig; - int res; - - if ((tx = sip_api_get_cpp_ptr(txSelf, sipQObjectClass)) == NULL) - return NULL; - - real_sig = sig; - - if ((tx = newSignal(tx, &real_sig)) == NULL) - return NULL; - - if ((rx = sip_api_convert_rx(txSelf, sig, rxObj, slot, &member)) == NULL) - return NULL; - - res = sipQtSupport->qt_connect(tx, real_sig, rx, member, type); - - return PyBool_FromLong(res); - } - - /* Handle Python signals. */ - if (addSlotToPySigList(txSelf, 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) -{ - sipWrapper *txSelf = (sipWrapper *)txObj; - - /* Handle Qt signals. */ - if (isQtSignal(sig)) - { - void *tx, *rx; - const char *member; - int res; - - if ((tx = sip_api_get_cpp_ptr(txSelf, sipQObjectClass)) == 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. */ - removeSlotFromPySigList(txSelf,sig,rxObj,slot); - - Py_INCREF(Py_True); - return Py_True; -} - - -/* - * Remove a slot from a transmitter's Python signal list. - */ -static void removeSlotFromPySigList(sipWrapper *txSelf,const char *sig, - PyObject *rxObj,const char *slot) -{ - sipPySig *ps; - - if ((ps = findPySignal(txSelf,sig)) != NULL) - { - sipSlotList **psrxp; - - for (psrxp = &ps -> rxlist; *psrxp != NULL; psrxp = &(*psrxp) -> next) - { - sipSlotList *psrx = *psrxp; - - if (isSameSlot(&psrx -> rx,rxObj,slot)) - { - *psrxp = psrx -> next; - sipFreeSlotList(psrx); - break; - } - } - } -} - - -/* - * Free a sipSlot structure. - */ -static void freeSlot(sipSlot *slot) -{ - if (slot->name != NULL) - sip_api_free(slot->name); - else - { - PyObject *lam = slot->pyobj; - - if (lam != NULL && (lam == Py_None || sipLambdaSlot(lam))) - Py_DECREF(lam); - } - - /* Remove any weak reference. */ - Py_XDECREF(slot->weakSlot); -} - - -/* - * Free a sipSlotList structure on the heap. - */ -void sipFreeSlotList(sipSlotList *rx) -{ - freeSlot(&rx->rx); - sip_api_free(rx); -} - - -/* - * 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. - */ -static int saveSlot(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 && - sip_api_wrapper_check(self)) - { - /* - * 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, TQT_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 - { - /* - * A bit of a hack to allow lamba functions to be used as - * slots. - */ - if (sipLambdaSlot(rxObj)) - Py_INCREF(rxObj); - - /* - * It's unlikely that we will succeed in getting a weak - * reference to the slot, but there is no harm in trying (and - * future versions of Python may support references to more - * object types). - */ - sp -> pyobj = rxObj; - sp -> weakSlot = getWeakRef(rxObj); - } - } - } - 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, TQT_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; -} - - -/* - * See if an object is a lambda function. - */ -int sipLambdaSlot(PyObject *slotObj) -{ - if (!PyFunction_Check(slotObj)) - return FALSE; - - return (strcmp(PyString_AsString(((PyFunctionObject *)slotObj)->func_name), "<lambda>") == 0); -} diff --git a/python/sip/siplib/sip.h b/python/sip/siplib/sip.h deleted file mode 100644 index 92bcda4e..00000000 --- a/python/sip/siplib/sip.h +++ /dev/null @@ -1,1302 +0,0 @@ -/* - * The SIP module interface. - * - * Copyright (c) 2007 - * Riverbank Computing Limited <info@riverbankcomputing.co.uk> - * - * 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. - * - * 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 0x040600 -#define SIP_VERSION_STR "4.6" - - -/* - * 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: - * - * 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 3 -#define SIP_API_MINOR_NR 4 - - -/* 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 -#else -#define SIP_SSIZE_T int -#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 metatype 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 additional type information. */ - struct _sipTypeDef *type; - - /* The list of init extenders. */ - struct _sipInitExtenderDef *iextend; - - /* The optional PyQt defined Q_OBJECT information. */ - void *qt_qobject; -} sipWrapperType; - - -/* - * The type of a C/C++ wrapper object. - */ -typedef struct _sipWrapper { - PyObject_HEAD - - /* For the user to use. */ - PyObject *user; - - union { - /* C/C++ object pointer. */ - void *cppPtr; - - /* Access function. */ - void *(*afPtr)(); - } u; - - /* Object flags. */ - int flags; - - /* The instance dictionary. */ - PyObject *dict; - - /* Python signal list (complex). */ - struct _sipPySig *pySigList; - - /* Next object at this address. */ - struct _sipWrapper *next; - - /* 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; - - -/* - * Some convenient function pointers. - */ -typedef void *(*sipInitFunc)(sipWrapper *, PyObject *, sipWrapper **, int *); -typedef int (*sipTraverseFunc)(void *, visitproc, void *); -typedef int (*sipClearFunc)(void *); -typedef SIP_SSIZE_T (*sipBufferFunc)(PyObject *, void *, SIP_SSIZE_T, void **); -typedef SIP_SSIZE_T (*sipSegCountFunc)(PyObject *, void *, SIP_SSIZE_T *); -typedef void (*sipDeallocFunc)(sipWrapper *); -typedef void *(*sipCastFunc)(void *, sipWrapperType *); -typedef sipWrapperType *(*sipSubClassConvertFunc)(void **); -typedef void *(*sipForceConvertToFunc)(PyObject *, int *); -typedef int (*sipConvertToFunc)(PyObject *, void **, int *, PyObject *); -typedef PyObject *(*sipConvertFromFunc)(void *, PyObject *); -typedef int (*sipVirtHandlerFunc)(void *, PyObject *, ...); -typedef int (*sipEmitFunc)(sipWrapper *, PyObject *); -typedef void (*sipReleaseFunc)(void *, int); - - -/* - * The information describing an encoded class ID. - */ -typedef struct _sipEncodedClassDef { - /* The class number. */ - unsigned sc_class:16; - - /* The module number (255 for this one). */ - unsigned sc_module:8; - - /* A context specific flag. */ - unsigned sc_flag:1; -} sipEncodedClassDef; - - -/* - * 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 a named enum. - */ -typedef struct _sipEnumDef { - /* The Python name of the enum. */ - const char *e_name; - - /* The C/C++ name of the enum, NULL if the same as the Python name. */ - const char *e_cname; - - /* The scoping type. */ - int e_scope; - - /* The Python slots. */ - struct _sipPySlotDef *e_pyslots; -} sipEnumDef; - - -/* - * The information describing static instances. - */ -typedef struct _sipInstancesDef { - /* The classes. */ - struct _sipClassInstanceDef *id_class; - - /* 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; - - /* The enums. */ - struct _sipEnumInstanceDef *id_enum; -} sipInstancesDef; - - -/* - * The information describing a type initialiser extender. - */ -typedef struct _sipInitExtenderDef { - /* The extender function. */ - sipInitFunc ie_extender; - - /* The class being extended. */ - sipEncodedClassDef 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. */ - sipEncodedClassDef scc_base; - - /* The base type. */ - sipWrapperType *scc_basetype; -} sipSubClassConvertorDef; - - -/* - * The different Python slot types. - */ -typedef enum { - str_slot, /* __str__ */ - int_slot, /* __int__ */ - long_slot, /* __long__ */ - 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__ */ - 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__ */ - 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__ */ - cmp_slot, /* __cmp__ */ - nonzero_slot, /* __nonzero__ */ - neg_slot, /* __neg__ */ - repr_slot, /* __repr__ */ - hash_slot, /* __hash__ */ - pos_slot, /* __pos__ */ - abs_slot /* __abs__ */ -} 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. */ - sipEncodedClassDef pse_class; -} sipPySlotExtenderDef; - - -/* - * This enumerates the different dynamic signal argument types. - */ -typedef enum { - unknown_sat, - char_sat, - uchar_sat, - string_sat, - ustring_sat, - short_sat, - ushort_sat, - int_sat, - uint_sat, - long_sat, - ulong_sat, - longlong_sat, - ulonglong_sat, - float_sat, - double_sat, - enum_sat, - bool_sat, - void_sat, - class_sat, - classp_sat, - mtype_sat, - mtypep_sat, - qvariant_sat, - qvariantp_sat, - pyobject_sat, - schar_sat, - sstring_sat, - wchar_sat, - wstring_sat -} sipSigArgType; - - -/* - * The information describing a typedef. - */ -typedef struct _sipTypedefDef { - /* The typedef name. */ - const char *tdd_name; - - /* The typedef type. */ - sipSigArgType tdd_type; - - /* The type name for enum_sat, class_sat and mtype_sat. */ - const char *tdd_type_name; - - /* The defining module, NULL if the current one. */ - const char *tdd_mod_name; -} sipTypedefDef; - - -/* - * The information describing a type. - */ -typedef struct _sipTypeDef { - /* The module. */ - struct _sipExportedModuleDef *td_module; - - /* Type flags, see the sipType*() macros. */ - int td_flags; - - /* The Python name of the type. */ - const char *td_name; - - /* The C/C++ name of the type, NULL if the same as the Python name. */ - const char *td_cname; - - /* The scoping type. */ - sipEncodedClassDef td_scope; - - /* The super-types. */ - sipEncodedClassDef *td_supers; - - /* The table of Python slots. */ - sipPySlotDef *td_pyslots; - - /* The number of lazy methods. */ - int td_nrmethods; - - /* The table of lazy methods. */ - PyMethodDef *td_methods; - - /* The number of lazy enum members. */ - int td_nrenummembers; - - /* The table of lazy enum members. */ - sipEnumMemberDef *td_enummembers; - - /* The variable table. */ - PyMethodDef *td_variables; - - /* The initialisation function. */ - sipInitFunc td_init; - - /* The traverse function. */ - sipTraverseFunc td_traverse; - - /* The clear function. */ - sipClearFunc td_clear; - - /* The read buffer function. */ - sipBufferFunc td_readbuffer; - - /* The write buffer function. */ - sipBufferFunc td_writebuffer; - - /* The segment count function. */ - sipSegCountFunc td_segcount; - - /* The char buffer function. */ - sipBufferFunc td_charbuffer; - - /* The deallocation function. */ - sipDeallocFunc td_dealloc; - - /* The cast function, 0 if a C struct. */ - sipCastFunc td_cast; - - /* The release function. */ - sipReleaseFunc td_release; - - /* The force convert to function, 0 if a C++ namespace. */ - sipForceConvertToFunc td_fcto; - - /* The convert to function. */ - sipConvertToFunc td_cto; - - /* Emit table for Qt signals. */ - struct _sipQtSignal *td_emit; - - /* The static instances. */ - sipInstancesDef td_instances; - - /* The next namespace extender. */ - struct _sipTypeDef *td_nsextender; -} sipTypeDef; - - -/* - * 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. - */ -typedef struct _sipMappedType { - /* The corresponding C++ definition. */ - const char *mt_name; - - /* The release function. */ - sipReleaseFunc mt_release; - - /* The force convert to function. */ - sipForceConvertToFunc mt_fcto; - - /* The convert to function. */ - sipConvertToFunc mt_cto; - - /* The convert from function. */ - sipConvertFromFunc mt_cfrom; -} 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; - - -/* - * 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. */ - const char *em_name; - - /* The module name as an object. */ - PyObject *em_nameobj; - - /* The module version. */ - int em_version; - - /* 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 type types. */ - struct _sipWrapperType **em_types; - - /* The table of external types. */ - sipExternalTypeDef *em_external; - - /* The table of mapped types. */ - sipMappedType **em_mappedtypes; - - /* The number of enums. */ - int em_nrenums; - - /* The table of enum types. */ - PyTypeObject **em_enums; - - /* The table of enum type data. */ - sipEnumDef *em_enumdefs; - - /* The number of members in global enums. */ - int em_nrenummembers; - - /* The table of members in global enums. */ - sipEnumMemberDef *em_enummembers; - - /* 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; -} 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; -} 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; -} 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 instance to be added to a dictionary. - */ -typedef struct _sipClassInstanceDef { - /* The class instance name. */ - const char *ci_name; - - /* The actual instance. */ - void *ci_ptr; - - /* A pointer to the Python type. */ - struct _sipWrapperType **ci_type; - - /* The wrapping flags. */ - int ci_flags; -} sipClassInstanceDef; - - -/* - * The information describing an enum instance to be added to a dictionary. - */ -typedef struct _sipEnumInstanceDef { - /* The enum instance name. */ - const char *ei_name; - - /* The enum value. */ - int ei_val; - - /* A pointer to the Python type. */ - PyTypeObject **ei_type; -} sipEnumInstanceDef; - - -/* - * Define a mapping between a wrapped type identified by a string and the - * corresponding Python type. - */ -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. - */ -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; - - /* The class. */ - PyObject *mclass; -} sipPyMethod; - - -/* - * Cache a reference to a Python member function. - */ -typedef struct _sipMethodCache { - /* Method cache flags. */ - int mcflags; - - /* The method. */ - sipPyMethod pyMethod; -} sipMethodCache; - - -/* - * 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. */ - PyObject *weakSlot; -} sipSlot; - - -/* - * An entry in a linked list of slots. - */ -typedef struct _sipSlotList { - /* The receiver. */ - sipSlot rx; - - /* Next in the list. */ - struct _sipSlotList *next; -} sipSlotList; - - -/* - * A Python signal. - */ -typedef struct _sipPySig { - /* The name of the signal. */ - char *name; - - /* The list of receivers. */ - sipSlotList *rxlist; - - /* Next in the list. */ - struct _sipPySig *next; -} sipPySig; - - -/* - * This defines a single dynamic signal argument type. - */ -typedef struct _sipSigArg { - /* The type. */ - sipSigArgType atype; - - union { - /* The Python type for classes. */ - sipWrapperType *wt; - - /* The data for mapped types. */ - sipMappedType *mt; - - /* The Python type for named enums. */ - PyTypeObject *et; - } u; -} sipSigArg; - - -/* - * A parsed signal signature. - */ -typedef struct _sipSignature { - /* The number of arguments. */ - int sg_nrargs; - - /* The parsed arguments (heap). */ - sipSigArg *sg_args; - - /* The unparsed signature (heap). */ - char *sg_signature; - - /* The next in the list. */ - struct _sipSignature *sg_next; -} sipSignature; - - -/* - * A connection to a universal slot. - */ -typedef struct _sipSlotConnection { - /* The transmitter TQObject. */ - void *sc_transmitter; - - /* The parsed signature. */ - const sipSignature *sc_signature; - - /* The slot. */ - sipSlot sc_slot; -} sipSlotConnection; - - -/* - * Maps the name of a Qt signal to a wrapper function to emit it. - */ -typedef struct _sipQtSignal { - /* The signal name. */ - char *st_name; - - /* The emitter function. */ - sipEmitFunc st_emitfunc; -} sipQtSignal; - - -/* - * 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, PyObject *mod_dict); - - /* - * The following are part of the public API. - */ - 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_class_name)(PyObject *self); - 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_instance)(PyObject *pyObj, sipWrapperType *type, - int flags); - int (*api_can_convert_to_mapped_type)(PyObject *pyObj, - const sipMappedType *mt, int flags); - void *(*api_convert_to_instance)(PyObject *pyObj, sipWrapperType *type, - PyObject *transferObj, int flags, int *statep, int *iserrp); - void *(*api_convert_to_mapped_type)(PyObject *pyObj, - const sipMappedType *mt, PyObject *transferObj, int flags, - int *statep, int *iserrp); - void *(*api_force_convert_to_instance)(PyObject *pyObj, - sipWrapperType *type, PyObject *transferObj, int flags, - int *statep, int *iserrp); - void *(*api_force_convert_to_mapped_type)(PyObject *pyObj, - const sipMappedType *mt, PyObject *transferObj, int flags, - int *statep, int *iserrp); - void (*api_release_instance)(void *cpp, sipWrapperType *type, int state); - void (*api_release_mapped_type)(void *cpp, const sipMappedType *mt, - int state); - PyObject *(*api_convert_from_instance)(void *cpp, sipWrapperType *type, - PyObject *transferObj); - PyObject *(*api_convert_from_new_instance)(void *cpp, sipWrapperType *type, - PyObject *transferObj); - PyObject *(*api_convert_from_mapped_type)(void *cpp, - const sipMappedType *mt, PyObject *transferObj); - void *(*api_convert_to_cpp)(PyObject *sipSelf, sipWrapperType *type, - int *iserrp); - int (*api_get_state)(PyObject *transferObj); - const sipMappedType *(*api_find_mapped_type)(const char *type); - PyObject *(*api_disconnect_rx)(PyObject *txObj, const char *sig, - PyObject *rxObj, const char *slot); - int (*api_emit_signal)(PyObject *self, const char *sig, PyObject *sigargs); - void (*api_free)(void *mem); - PyObject *(*api_get_sender)(); - PyObject *(*api_get_wrapper)(void *cppPtr, sipWrapperType *type); - void *(*api_malloc)(size_t nbytes); - 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); - int (*api_parse_result)(int *isErr, PyObject *method, PyObject *res, - const char *fmt, ...); - void (*api_trace)(unsigned mask, const char *fmt, ...); - void (*api_transfer)(PyObject *self, int toCpp); - void (*api_transfer_back)(PyObject *self); - void (*api_transfer_to)(PyObject *self, PyObject *owner); - int (*api_wrapper_check)(PyObject *o); - unsigned long (*api_long_as_unsigned_long)(PyObject *o); - PyObject *(*api_convert_from_named_enum)(int eval, PyTypeObject *et); - - /* - * The following may be used by Qt support code but no other handwritten - * code. - */ - PyObject *(*api_convert_from_void_ptr)(void *val); - void (*api_free_connection)(sipSlotConnection *conn); - int (*api_emit_to_slot)(sipSlot *slot, PyObject *sigargs); - int (*api_same_connection)(sipSlotConnection *conn, void *tx, - const char *sig, PyObject *rxObj, const char *slot); - void *(*api_convert_rx)(sipWrapper *txSelf, const char *sigargs, - PyObject *rxObj, const char *slot, const char **memberp); - - /* - * The following are not part of the public API. - */ - int (*api_parse_args)(int *argsParsedp, PyObject *sipArgs, - const char *fmt, ...); - int (*api_parse_pair)(int *argsParsedp, PyObject *arg0, PyObject *arg1, - const char *fmt, ...); - void (*api_common_ctor)(sipMethodCache *cache, int nrmeths); - void (*api_common_dtor)(sipWrapper *sipSelf); - void *(*api_convert_to_void_ptr)(PyObject *obj); - void (*api_no_function)(int argsParsed, const char *func); - void (*api_no_method)(int argsParsed, const char *classname, - const char *method); - void (*api_abstract_method)(const char *classname, const char *method); - void (*api_bad_class)(const char *classname); - void (*api_bad_set_type)(const char *classname, const char *var); - void *(*api_get_cpp_ptr)(sipWrapper *w, sipWrapperType *type); - void *(*api_get_complex_cpp_ptr)(sipWrapper *w); - PyObject *(*api_is_py_method)(sip_gilstate_t *gil, sipMethodCache *pymc, - sipWrapper *sipSelf, char *cname, 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_class_exception)(sipWrapperType *type, void *ptr); - void (*api_raise_sub_class_exception)(sipWrapperType *type, void *ptr); - int (*api_add_class_instance)(PyObject *dict, const char *name, - void *cppPtr, sipWrapperType *wt); - int (*api_add_enum_instance)(PyObject *dict, const char *name, int value, - PyTypeObject *type); - void (*api_bad_operator_arg)(PyObject *self, PyObject *arg, - sipPySlotType st); - PyObject *(*api_pyslot_extend)(sipExportedModuleDef *mod, sipPySlotType st, - sipWrapperType *type, PyObject *arg0, PyObject *arg1); - void (*api_add_delayed_dtor)(sipWrapper *w); - int (*api_add_mapped_type_instance)(PyObject *dict, const char *name, - void *cppPtr, const sipMappedType *mt); - - /* - * The following are part of the public API. - */ - int (*api_export_symbol)(const char *name, void *sym); - void *(*api_import_symbol)(const char *name); - - /* - * The following may be used by Qt support code but no other handwritten - * code. - */ - int (*api_register_int_types)(PyObject *args); - sipSignature *(*api_parse_signature)(const char *sig); - - /* - * The following are part of the public API. - */ - sipWrapperType *(*api_find_class)(const char *type); - PyTypeObject *(*api_find_named_enum)(const char *type); - - /* - * The following are not part of the public API. - */ - char (*api_string_as_char)(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 -} sipAPIDef; - - -/* - * The API implementing the optional Qt support. - */ -typedef struct _sipQtAPI { - struct _sipWrapperType **qt_qobject; - int (*qt_is_qt_signal)(void *, const char *); - void *(*qt_create_universal_signal_shortcut)(void *, const char *, - const char **); - void *(*qt_create_universal_signal)(void *, const struct _sipSignature *); - void *(*qt_find_universal_signal_shortcut)(void *, const char *, - const char **); - void *(*qt_find_universal_signal)(void *, const struct _sipSignature *); - int (*qt_emit_signal_shortcut)(void *, const char *, PyObject *); - int (*qt_emit_signal)(void *, const struct _sipSignature *, PyObject *); - void *(*qt_create_universal_slot)(struct _sipWrapper *, - struct _sipSlotConnection *, const char **); - 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_signals_blocked)(void *); - const void *(*qt_get_sender)(); - void (*qt_forget_sender)(); - int (*qt_same_name)(const char *, const char *); - sipSlotConnection *(*qt_find_connection)(void *, void **); -} sipQtAPI; - - -/* - * These are flags that can be passed to sipCanConvertToInstance(), - * sipConvertToInstance() and sipForceConvertToInstance(). - */ -#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. */ - - -/* - * 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 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 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 SIP_TYPE_ABSTRACT 0x0001 /* If the type is abstract. */ -#define SIP_TYPE_SCC 0x0002 /* If the type is subject to sub-class convertors. */ -#define SIP_TYPE_FLAGS_SHIFT 8 /* The user type flags shift. */ -#define SIP_TYPE_FLAGS_MASK 0x0f00 /* The user type flags mask. */ - -#define sipTypeIsAbstract(wt) ((wt)->type->td_flags & SIP_TYPE_ABSTRACT) -#define sipTypeHasSCC(wt) ((wt)->type->td_flags & SIP_TYPE_SCC) -#define sipTypeFlags(wt) (((wt)->type->td_flags & SIP_TYPE_FLAGS_MASK) >> SIP_TYPE_FLAGS_SHIFT) - - -#ifdef __cplusplus -} -#endif - - -#endif diff --git a/python/sip/siplib/sipint.h b/python/sip/siplib/sipint.h deleted file mode 100644 index 0a8f2459..00000000 --- a/python/sip/siplib/sipint.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * This file defines the SIP library internal interfaces. - * - * Copyright (c) 2007 - * Riverbank Computing Limited <info@riverbankcomputing.co.uk> - * - * 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. - * - * 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. */ - sipWrapper *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; - - -extern PyInterpreterState *sipInterpreter; /* The interpreter. */ - - -extern sipQtAPI *sipQtSupport; /* The Qt support API. */ -extern sipWrapperType *sipQObjectClass; /* The Python TQObject class. */ - -void *sip_api_convert_rx(sipWrapper *txSelf, const char *sigargs, - PyObject *rxObj, const char *slot, - const char **memberp); -void *sipGetRx(sipWrapper *txSelf,const char *sigargs,PyObject *rxObj, - const char *slot,const char **memberp); -int sip_api_emit_signal(PyObject *self,const char *sig,PyObject *sigargs); -PyObject *sip_api_get_sender(); -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); -sipSignature *sip_api_parse_signature(const char *sig); - - -/* - * 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(sipWrapper *w,sipWrapperType *type); -PyObject *sip_api_convert_from_instance(void *cppPtr, sipWrapperType *type, - PyObject *transferObj); -void sip_api_start_thread(void); -void sip_api_end_thread(void); -PyObject *sip_api_convert_from_void_ptr(void *val); -PyObject *sip_api_convert_from_named_enum(int eval, PyTypeObject *et); -int sip_api_wrapper_check(PyObject *o); -void sip_api_free_connection(sipSlotConnection *conn); -int sip_api_emit_to_slot(sipSlot *slot, PyObject *sigargs); -int sip_api_same_connection(sipSlotConnection *conn, void *tx, const char *sig, - PyObject *rxObj, const char *slot); - - -/* - * These are not part of the SIP API but are used within the SIP module. - */ -void sipFreeSlotList(sipSlotList *rx); -void sipSaveMethod(sipPyMethod *pm,PyObject *meth); -void *sipGetPending(sipWrapper **op, int *fp); -PyObject *sipWrapSimpleInstance(void *cppPtr, sipWrapperType *type, - sipWrapper *owner, int initflags); -int sipLambdaSlot(PyObject *slotObj); - -void sipOMInit(sipObjectMap *om); -void sipOMFinalise(sipObjectMap *om); -sipWrapper *sipOMFindObject(sipObjectMap *om,void *key,sipWrapperType *type); -void sipOMAddObject(sipObjectMap *om,sipWrapper *val); -int sipOMRemoveObject(sipObjectMap *om,sipWrapper *val); - -void sipSetBool(void *ptr,int val); - -void *sipGetAddress(sipWrapper *w); -void sipFindSigArgType(const char *name, size_t len, sipSigArg *at, int indir); - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/python/sip/siplib/siplib.c b/python/sip/siplib/siplib.c deleted file mode 100644 index a715e830..00000000 --- a/python/sip/siplib/siplib.c +++ /dev/null @@ -1,7902 +0,0 @@ -/* - * SIP library code. - * - * Copyright (c) 2007 - * Riverbank Computing Limited <info@riverbankcomputing.co.uk> - * - * 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. - * - * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - - -#include <Python.h> -#include <stdio.h> -#include <stdarg.h> -#include <stddef.h> -#include <string.h> - -#include "sip.h" -#include "sipint.h" - - -/* - * These are the functions that make up the public and private SIP API. - */ -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 PyObject *sip_api_class_name(PyObject *self); -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_instance(PyObject *pyObj, - sipWrapperType *type, int flags); -static int sip_api_can_convert_to_mapped_type(PyObject *pyObj, - const sipMappedType *mt, int flags); -static void *sip_api_convert_to_instance(PyObject *pyObj, sipWrapperType *type, - PyObject *transferObj, int flags, int *statep, int *iserrp); -static void *sip_api_convert_to_mapped_type(PyObject *pyObj, - const sipMappedType *mt, PyObject *transferObj, int flags, int *statep, - int *iserrp); -static void *sip_api_force_convert_to_instance(PyObject *pyObj, - sipWrapperType *type, PyObject *transferObj, int flags, int *statep, - int *iserrp); -static void *sip_api_force_convert_to_mapped_type(PyObject *pyObj, - const sipMappedType *mt, PyObject *transferObj, int flags, int *statep, - int *iserrp); -static void sip_api_release_instance(void *cpp, sipWrapperType *type, - int state); -static void sip_api_release_mapped_type(void *cpp, const sipMappedType *mt, - int state); -static PyObject *sip_api_convert_from_new_instance(void *cpp, - sipWrapperType *type, PyObject *transferObj); -static PyObject *sip_api_convert_from_mapped_type(void *cpp, - const sipMappedType *mt, PyObject *transferObj); -static void *sip_api_convert_to_cpp(PyObject *sipSelf, sipWrapperType *type, - int *iserrp); -static int sip_api_get_state(PyObject *transferObj); -static const sipMappedType *sip_api_find_mapped_type(const char *type); -static PyObject *sip_api_get_wrapper(void *cppPtr, sipWrapperType *type); -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(PyObject *self, int toCpp); -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, PyObject *mod_dict); -static int sip_api_parse_args(int *argsParsedp, PyObject *sipArgs, - const char *fmt, ...); -static int sip_api_parse_pair(int *argsParsedp, PyObject *sipArg0, - PyObject *sipArg1, const char *fmt, ...); -static void sip_api_common_ctor(sipMethodCache *cache, int nrmeths); -static void sip_api_common_dtor(sipWrapper *sipSelf); -static void *sip_api_convert_to_void_ptr(PyObject *obj); -static void sip_api_no_function(int argsParsed, const char *func); -static void sip_api_no_method(int argsParsed, const char *classname, - const char *method); -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_bad_set_type(const char *classname, const char *var); -static void *sip_api_get_complex_cpp_ptr(sipWrapper *w); -static PyObject *sip_api_is_py_method(sip_gilstate_t *gil, - sipMethodCache *pymc, sipWrapper *sipSelf, char *cname, char *mname); -static void sip_api_call_hook(const char *hookname); -static void sip_api_raise_unknown_exception(void); -static void sip_api_raise_class_exception(sipWrapperType *type, void *ptr); -static void sip_api_raise_sub_class_exception(sipWrapperType *type, void *ptr); -static int sip_api_add_class_instance(PyObject *dict, const char *name, - void *cppPtr, sipWrapperType *wt); -static int sip_api_add_mapped_type_instance(PyObject *dict, const char *name, - void *cppPtr, const sipMappedType *mt); -static int sip_api_add_enum_instance(PyObject *dict, const char *name, - int value, PyTypeObject *type); -static void sip_api_bad_operator_arg(PyObject *self, PyObject *arg, - sipPySlotType st); -static PyObject *sip_api_pyslot_extend(sipExportedModuleDef *mod, - sipPySlotType st, sipWrapperType *type, PyObject *arg0, - PyObject *arg1); -static void sip_api_add_delayed_dtor(sipWrapper *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 int sip_api_register_int_types(PyObject *args); -static sipWrapperType *sip_api_find_class(const char *type); -static PyTypeObject *sip_api_find_named_enum(const char *type); -static char sip_api_string_as_char(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 - - -/* - * 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. - */ - sip_api_bad_catcher_result, - sip_api_bad_length_for_slice, - sip_api_build_result, - sip_api_call_method, - sip_api_class_name, - sip_api_connect_rx, - sip_api_convert_from_sequence_index, - sip_api_can_convert_to_instance, - sip_api_can_convert_to_mapped_type, - sip_api_convert_to_instance, - sip_api_convert_to_mapped_type, - sip_api_force_convert_to_instance, - sip_api_force_convert_to_mapped_type, - sip_api_release_instance, - sip_api_release_mapped_type, - sip_api_convert_from_instance, - sip_api_convert_from_new_instance, - sip_api_convert_from_mapped_type, - sip_api_convert_to_cpp, - sip_api_get_state, - sip_api_find_mapped_type, - sip_api_disconnect_rx, - sip_api_emit_signal, - sip_api_free, - sip_api_get_sender, - sip_api_get_wrapper, - sip_api_malloc, - sip_api_map_int_to_class, - sip_api_map_string_to_class, - sip_api_parse_result, - sip_api_trace, - sip_api_transfer, - sip_api_transfer_back, - sip_api_transfer_to, - sip_api_wrapper_check, - sip_api_long_as_unsigned_long, - /* - * The following may be used by Qt support code but by no other handwritten - * code. - */ - sip_api_convert_from_named_enum, - sip_api_convert_from_void_ptr, - sip_api_free_connection, - sip_api_emit_to_slot, - sip_api_same_connection, - sip_api_convert_rx, - /* - * The following are not part of the public API. - */ - sip_api_parse_args, - sip_api_parse_pair, - sip_api_common_ctor, - sip_api_common_dtor, - sip_api_convert_to_void_ptr, - sip_api_no_function, - sip_api_no_method, - sip_api_abstract_method, - sip_api_bad_class, - sip_api_bad_set_type, - 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_class_exception, - sip_api_raise_sub_class_exception, - sip_api_add_class_instance, - sip_api_add_enum_instance, - sip_api_bad_operator_arg, - sip_api_pyslot_extend, - sip_api_add_delayed_dtor, - sip_api_add_mapped_type_instance, - /* - * The following are part of the public API. - */ - sip_api_export_symbol, - sip_api_import_symbol, - /* - * The following may be used by Qt support code but by no other handwritten - * code. - */ - sip_api_register_int_types, - sip_api_parse_signature, - /* - * The following are part of the public API. - */ - sip_api_find_class, - sip_api_find_named_enum, - /* - * The following are not part of the public API. - */ - sip_api_string_as_char, - sip_api_unicode_as_wchar, - sip_api_unicode_as_wstring, -}; - - -#define PARSE_OK 0x00000000 /* Parse is Ok so far. */ -#define PARSE_MANY 0x10000000 /* Too many arguments. */ -#define PARSE_FEW 0x20000000 /* Too few arguments. */ -#define PARSE_TYPE 0x30000000 /* Argument with a bad type. */ -#define PARSE_UNBOUND 0x40000000 /* Unbound method. */ -#define PARSE_FORMAT 0x50000000 /* Bad format character. */ -#define PARSE_RAISED 0x60000000 /* Exception already raised. */ -#define PARSE_STICKY 0x80000000 /* The error sticks. */ -#define PARSE_MASK 0xf0000000 - -/* - * Note that some of the following flags safely share values because they - * cannot be used at the same time. - */ -#define FORMAT_DEREF 0x01 /* The pointer will be dereferenced. */ -#define FORMAT_FACTORY 0x02 /* Implement /Factory/ in a VH. */ -#define FORMAT_TRANSFER 0x02 /* Implement /Transfer/. */ -#define FORMAT_NO_STATE 0x04 /* Don't return the C/C++ state. */ -#define FORMAT_TRANSFER_BACK 0x04 /* Implement /TransferBack/. */ -#define FORMAT_GET_WRAPPER 0x08 /* Implement /GetWrapper/. */ -#define FORMAT_NO_CONVERTORS 0x10 /* Suppress any convertors. */ -#define FORMAT_TRANSFER_THIS 0x20 /* Support for /TransferThis/. */ - -#define SIP_MC_FOUND 0x01 /* If we have looked for the method. */ -#define SIP_MC_ISMETH 0x02 /* If we looked and there was one. */ - -#define sipFoundMethod(m) ((m)->mcflags & SIP_MC_FOUND) -#define sipSetFoundMethod(m) ((m)->mcflags |= SIP_MC_FOUND) -#define sipIsMethod(m) ((m)->mcflags & SIP_MC_ISMETH) -#define sipSetIsMethod(m) ((m)->mcflags |= SIP_MC_ISMETH) - - -/* - * 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; - - -static PyTypeObject sipWrapperType_Type; -static sipWrapperType sipWrapper_Type; -static PyTypeObject sipVoidPtr_Type; - -PyInterpreterState *sipInterpreter = NULL; -sipQtAPI *sipQtSupport = NULL; -sipWrapperType *sipQObjectClass; -sipPyObject *sipRegisteredIntTypes = NULL; -sipSymbol *sipSymbolList = NULL; - - -/* - * 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 *clientList = NULL; /* List of registered clients. */ -static unsigned traceMask = 0; /* The current trace mask. */ - -static sipTypeDef *currentType = NULL; /* The type being created. */ - - -static void addSlots(sipWrapperType *wt, sipTypeDef *td); -static void initSlots(PyTypeObject *to, PyNumberMethods *nb, - PySequenceMethods *sq, PyMappingMethods *mp, sipPySlotDef *slots, - int force); -static void *findSlot(PyObject *self, sipPySlotType st); -static void *findSlotInType(sipTypeDef *td, 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 parsePass1(sipWrapper **selfp, int *selfargp, int *argsParsedp, - PyObject *sipArgs, const char *fmt, va_list va); -static int parsePass2(sipWrapper *self, int selfarg, int nrargs, - PyObject *sipArgs, const char *fmt, va_list va); -static int getSelfFromArgs(sipWrapperType *type, PyObject *args, int argnr, - sipWrapper **selfp); -static PyObject *createEnumMember(sipTypeDef *td, sipEnumMemberDef *enm); -static PyObject *handleGetLazyAttr(PyObject *nameobj, sipWrapperType *wt, - sipWrapper *w); -static int handleSetLazyAttr(PyObject *nameobj, PyObject *valobj, - sipWrapperType *wt, sipWrapper *w); -static int getNonStaticVariables(sipWrapperType *wt, sipWrapper *w, - PyObject **ndict); -static void findLazyAttr(sipWrapperType *wt, char *name, PyMethodDef **pmdp, - sipEnumMemberDef **enmp, PyMethodDef **vmdp, sipTypeDef **in); -static int compareMethodName(const void *key, const void *el); -static int compareEnumMemberName(const void *key, const void *el); -static int checkPointer(void *ptr); -static void *cast_cpp_ptr(void *ptr, sipWrapperType *src_type, - sipWrapperType *dst_type); -static void badArgs(int argsParsed, const char *classname, const char *method); -static void finalise(void); -static sipWrapperType *createType(sipExportedModuleDef *client, - sipTypeDef *type, PyObject *mod_dict); -static PyTypeObject *createEnum(sipExportedModuleDef *client, sipEnumDef *ed, - PyObject *mod_dict); -static const char *getBaseName(const char *name); -static PyObject *getBaseNameObject(const char *name); -static PyObject *createTypeDict(PyObject *mname); -static sipExportedModuleDef *getClassModule(sipEncodedClassDef *enc, - sipExportedModuleDef *em); -static sipWrapperType *getClassType(sipEncodedClassDef *enc, - sipExportedModuleDef *em); -static sipWrapperType *convertSubClass(sipWrapperType *type, void **cppPtr); -static void *getPtrTypeDef(sipWrapper *self, sipTypeDef **td); -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 addEnumInstances(PyObject *dict, sipEnumInstanceDef *ei); -static int addSingleEnumInstance(PyObject *dict, const char *name, int value, - PyTypeObject *type); -static int addClassInstances(PyObject *dict, sipClassInstanceDef *ci); -static int addSingleClassInstance(PyObject *dict, const char *name, - void *cppPtr, sipWrapperType *wt, 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 *isDeleted(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 *transfer(PyObject *self, PyObject *args); -static PyObject *transferBack(PyObject *self, PyObject *args); -static PyObject *transferTo(PyObject *self, PyObject *args); -static int sipWrapperType_Check(PyObject *op); -static void addToParent(sipWrapper *self, sipWrapper *owner); -static void removeFromParent(sipWrapper *self); -static sipWrapperType *findClass(sipExportedModuleDef *emd, const char *name, - size_t len); -static int findClassArg(sipExportedModuleDef *emd, const char *name, - size_t len, sipSigArg *at, int indir); -static int findMtypeArg(sipMappedType **mttab, const char *name, size_t len, - sipSigArg *at, int indir); -static PyTypeObject *findEnum(sipExportedModuleDef *emd, const char *name, - size_t len); -static int findEnumArg(sipExportedModuleDef *emd, const char *name, size_t len, - sipSigArg *at, int indir); -static int sameScopedName(const char *pyname, const char *name, size_t len); -static int nameEq(const char *with, const char *name, size_t len); -static int isExactWrappedType(sipWrapperType *wt); -static void release(void *addr, sipTypeDef *td, int state); -static void callPyDtor(sipWrapper *self); -static int qt_and_sip_api_3_4(void); -static int visitSlot(sipSlot *slot, visitproc visit, void *arg); -static void clearAnyLambda(sipSlot *slot); -static int parseCharArray(PyObject *obj, char **ap, int *aszp); -static int parseChar(PyObject *obj, char *ap); -static int parseCharString(PyObject *obj, char **ap); -#if defined(HAVE_WCHAR_H) -static int parseWCharArray(PyObject *obj, wchar_t **ap, int *aszp); -static int parseWChar(PyObject *obj, wchar_t *ap); -static int parseWCharString(PyObject *obj, wchar_t **ap); -#else -static void raiseNoWChar(); -#endif - - -/* - * The Python module initialisation function. - */ -#if defined(SIP_STATIC_MODULE) -void initsip(void) -#else -PyMODINIT_FUNC initsip(void) -#endif -{ - static PyMethodDef methods[] = { - {"cast", cast, METH_VARARGS, NULL}, - {"delete", callDtor, METH_VARARGS, NULL}, - {"isdeleted", isDeleted, METH_VARARGS, NULL}, - {"setdeleted", setDeleted, METH_VARARGS, NULL}, - {"settracemask", setTraceMask, METH_VARARGS, NULL}, - {"transfer", transfer, METH_VARARGS, NULL}, - {"transferback", transferBack, METH_VARARGS, NULL}, - {"transferto", transferTo, METH_VARARGS, NULL}, - {"wrapinstance", wrapInstance, METH_VARARGS, NULL}, - {"unwrapinstance", unwrapInstance, METH_VARARGS, NULL}, - {NULL, NULL, 0, NULL} - }; - - 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) - Py_FatalError("sip: Failed to initialise sip.wrappertype type"); - - if (PyType_Ready((PyTypeObject *)&sipWrapper_Type) < 0) - Py_FatalError("sip: Failed to initialise sip.wrapper type"); - - if (PyType_Ready(&sipVoidPtr_Type) < 0) - Py_FatalError("sip: Failed to initialise sip.voidptr type"); - - mod = Py_InitModule("sip", methods); - mod_dict = PyModule_GetDict(mod); - - /* Publish the SIP API. */ - if ((obj = PyCObject_FromVoidPtr((void *)&sip_api, NULL)) == NULL) - Py_FatalError("sip: Failed to create _C_API object"); - - rc = PyDict_SetItemString(mod_dict, "_C_API", obj); - Py_DECREF(obj); - - if (rc < 0) - Py_FatalError("sip: Failed to add _C_API object to module dictionary"); - - /* Add the SIP version number, but don't worry about errors. */ - if ((obj = PyInt_FromLong(SIP_VERSION)) != NULL) - { - PyDict_SetItemString(mod_dict, "SIP_VERSION", obj); - Py_DECREF(obj); - } - - if ((obj = PyString_FromString(SIP_VERSION_STR)) != 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, "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; - } -} - - -/* - * 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; -} - - -/* - * 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 (!sip_api_wrapper_check(owner)) - { - PyErr_Format(PyExc_TypeError, "transferto() argument 2 must be sip.wrapper, not %s", owner->ob_type->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; -} - - -/* - * Transfer the ownership of an instance. This is deprecated. - */ -static PyObject *transfer(PyObject *self, PyObject *args) -{ - PyObject *w; - int toCpp; - - if (PyArg_ParseTuple(args, "O!i:transfer", &sipWrapper_Type, &w, &toCpp)) - { - if (toCpp) - sip_api_transfer_to(w, NULL); - else - 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) -{ - sipWrapper *w; - sipWrapperType *wt, *type; - void *addr; - PyTypeObject *ft, *tt; - - if (!PyArg_ParseTuple(args, "O!O!:cast", &sipWrapper_Type, &w, &sipWrapperType_Type, &wt)) - return NULL; - - ft = ((PyObject *)w)->ob_type; - tt = (PyTypeObject *)wt; - - if (ft == tt || PyType_IsSubtype(tt, ft)) - type = NULL; - else if (PyType_IsSubtype(ft, tt)) - type = wt; - 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(w, type)) == 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, NULL, (w->flags | SIP_NOT_IN_MAP) & ~SIP_PY_OWNED); -} - - -/* - * Call an instance's dtor. - */ -static PyObject *callDtor(PyObject *self, PyObject *args) -{ - sipWrapper *w; - void *addr; - sipTypeDef *td; - - if (!PyArg_ParseTuple(args, "O!:delete", &sipWrapper_Type, &w)) - return NULL; - - addr = getPtrTypeDef(w, &td); - - if (checkPointer(addr) < 0) - return NULL; - - /* - * Transfer ownership to C++ so we don't try to release it again when the - * Python object is garbage collected. - */ - removeFromParent(w); - sipResetPyOwned(w); - - release(addr, td, w->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) -{ - sipWrapper *w; - PyObject *res; - - if (!PyArg_ParseTuple(args, "O!:isdeleted", &sipWrapper_Type, &w)) - return NULL; - - res = (sipGetAddress(w) == NULL ? Py_True : Py_False); - - Py_INCREF(res); - return res; -} - - -/* - * Mark an instance as having been deleted. - */ -static PyObject *setDeleted(PyObject *self, PyObject *args) -{ - sipWrapper *w; - - if (!PyArg_ParseTuple(args, "O!:setdeleted", &sipWrapper_Type, &w)) - return NULL; - - /* - * Transfer ownership to C++ so we don't try to release it when the Python - * object is garbage collected. - */ - removeFromParent(w); - sipResetPyOwned(w); - - w->u.cppPtr = NULL; - - Py_INCREF(Py_None); - return Py_None; -} - - -/* - * Unwrap an instance. - */ -static PyObject *unwrapInstance(PyObject *self, PyObject *args) -{ - sipWrapper *w; - - if (PyArg_ParseTuple(args, "O!:unwrapinstance", &sipWrapper_Type, &w)) - { - 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(w, 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_instance((void *)addr, wt, NULL); - - return NULL; -} - - -/* - * Register a client module. A negative value is returned and an exception - * raised if there was an error. Not normally needed by handwritten code. - */ -static int sip_api_export_module(sipExportedModuleDef *client, - unsigned api_major, unsigned api_minor, PyObject *mod_dict) -{ - sipExportedModuleDef *em; - sipImportedModuleDef *im; - sipSubClassConvertorDef *scc; - sipWrapperType **mw; - sipEnumMemberDef *emd; - sipInitExtenderDef *ie; - int i; - - /* 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 supports 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, client->em_name, api_major,api_minor); -#else - PyErr_Format(PyExc_RuntimeError, "the sip module supports API v%d.0 but the %s module requires API v%d.%d", SIP_API_MAJOR_NR, client->em_name, api_major,api_minor); -#endif - - return -1; - } - - /* Convert the module name to an object. */ - if ((client->em_nameobj = PyString_FromString(client->em_name)) == NULL) - return -1; - - for (em = clientList; em != NULL; em = em->em_next) - { - /* SIP clients must have unique names. */ - if (strcmp(em->em_name, client->em_name) == 0) - { - PyErr_Format(PyExc_RuntimeError, "the sip module has already registered a module called %s", client->em_name); - - return -1; - } - - /* Only one module can claim to wrap TQObject. */ - if (em->em_qt_api != NULL && client->em_qt_api != NULL) - { - PyErr_Format(PyExc_RuntimeError, "the %s and %s modules both wrap the TQObject class", client->em_name, em->em_name); - - return -1; - } - } - - /* Import any required modules. */ - if ((im = client->em_imports) != NULL) - { - while (im->im_name != NULL) - { - PyObject *mod; - - if ((mod = PyImport_ImportModule(im->im_name)) == NULL) - return -1; - - for (em = clientList; em != NULL; em = em->em_next) - if (strcmp(em->em_name, 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", em->em_name, em->em_version, client->em_name, im->im_version); - - return -1; - } - - /* Save the imported module. */ - im->im_module = em; - - ++im; - } - } - - /* Create the module's classes. */ - if ((mw = client->em_types) != NULL) - for (i = 0; i < client->em_nrtypes; ++i, ++mw) - { - sipTypeDef *td = (sipTypeDef *)*mw; - - /* Skip external classes. */ - if (td == NULL) - continue; - - /* See if this is a namespace extender. */ - if (td->td_name == NULL) - { - sipTypeDef **last; - sipWrapperType *wt = getClassType(&td->td_scope, client); - - /* Append this type to the real one. */ - last = &wt->type->td_nsextender; - - while (*last != NULL) - last = &(*last)->td_nsextender; - - *last = td; - - /* - * Set this so that the extender's original - * module can be found. - */ - td->td_module = client; - - /* - * Save the real namespace type so that it is - * the correct scope for any enums or classes - * defined in this module. - */ - *mw = wt; - } - else if ((*mw = createType(client, td, mod_dict)) == NULL) - return -1; - } - - /* Set any Qt support API. */ - if (client->em_qt_api != NULL) - { - sipQtSupport = client->em_qt_api; - sipQObjectClass = *sipQtSupport->qt_qobject; - } - - /* Append any initialiser extenders to the relevant classes. */ - if ((ie = client->em_initextend) != NULL) - while (ie->ie_extender != NULL) - { - sipWrapperType *wt = getClassType(&ie->ie_class, client); - - ie->ie_next = wt->iextend; - wt->iextend = ie; - - ++ie; - } - - /* Set the base class object for any sub-class convertors. */ - if ((scc = client->em_convertors) != NULL) - while (scc->scc_convertor != NULL) - { - scc->scc_basetype = getClassType(&scc->scc_base, client); - - ++scc; - } - - /* Create the module's enums. */ - if (client->em_nrenums != 0) - { - if ((client->em_enums = sip_api_malloc(client->em_nrenums * sizeof (PyTypeObject *))) == NULL) - return -1; - - for (i = 0; i < client->em_nrenums; ++i) - if ((client->em_enums[i] = createEnum(client, &client->em_enumdefs[i], mod_dict)) == NULL) - return -1; - } - - for (emd = client->em_enummembers, i = 0; i < client->em_nrenummembers; ++i, ++emd) - { - PyObject *mo; - - if ((mo = sip_api_convert_from_named_enum(emd->em_val, client->em_enums[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. - */ - if ((mw = client->em_types) != NULL) - for (i = 0; i < client->em_nrtypes; ++i) - { - sipWrapperType *wt; - - if ((wt = *mw++) != NULL && addInstances(((PyTypeObject *)wt)->tp_dict, &wt->type->td_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 = clientList; em != NULL; em = em->em_next) - { - sipExternalTypeDef *etd; - - if (em->em_external == NULL) - continue; - - for (etd = em->em_external; etd->et_nr >= 0; ++etd) - { - if (etd->et_name == NULL) - continue; - - mw = client->em_types; - - for (i = 0; i < client->em_nrtypes; ++i) - { - sipWrapperType *wt; - const char *tname; - - if ((wt = *mw++) == NULL) - continue; - - tname = strchr(wt->type->td_name, '.') + 1; - - if (strcmp(etd->et_name, tname) == 0) - { - em->em_types[etd->et_nr] = wt; - etd->et_name = NULL; - - break; - } - } - } - } - - /* Add to the list of client modules. */ - client->em_next = clientList; - clientList = client; - - 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 = clientList; 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. */ - clientList = NULL; -} - - -/* - * Add a wrapped C/C++ pointer to the list of delayed dtors. - */ -static void sip_api_add_delayed_dtor(sipWrapper *w) -{ - void *ptr; - sipTypeDef *td; - sipExportedModuleDef *em; - - if ((ptr = getPtrTypeDef(w, &td)) == NULL) - return; - - /* Find the defining module. */ - for (em = clientList; em != NULL; em = em->em_next) - { - int i; - - for (i = 0; i < em->em_nrtypes; ++i) - if (em->em_types[i] != NULL && em->em_types[i]->type == td) - { - sipDelayedDtor *dd; - - if ((dd = sip_api_malloc(sizeof (sipDelayedDtor))) == NULL) - return; - - /* Add to the list. */ - dd->dd_ptr = ptr; - dd->dd_name = getBaseName(td->td_name); - dd->dd_isderived = sipIsDerived(w); - 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, sipWrapperType *type, - PyObject *arg0, PyObject *arg1) -{ - sipExportedModuleDef *em; - - /* Go through each module. */ - for (em = clientList; 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 (type != NULL && type != getClassType(&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 'a': - { - char *s; - int l; - - s = va_arg(va, char *); - l = va_arg(va, int); - - if (s != NULL) - el = PyString_FromStringAndSize(s, (SIP_SSIZE_T)l); - else - { - Py_INCREF(Py_None); - el = Py_None; - } - } - - break; - - case 'A': -#if defined(HAVE_WCHAR_H) - { - wchar_t *s; - int l; - - s = va_arg(va, wchar_t *); - l = va_arg(va, int); - - if (s != NULL) - el = PyUnicode_FromWideChar(s, (SIP_SSIZE_T)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 = PyString_FromStringAndSize(&c,1); - } - - 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': - el = PyInt_FromLong(va_arg(va,int)); - break; - - case 'E': - { - int ev = va_arg(va, int); - PyTypeObject *et = va_arg(va, PyTypeObject *); - - el = sip_api_convert_from_named_enum(ev, et); - } - - break; - - case 'd': - case 'f': - el = PyFloat_FromDouble(va_arg(va,double)); - break; - - case 'h': - case 'i': - el = PyInt_FromLong(va_arg(va,int)); - 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 = PyString_FromString(s); - 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': - { - void *p = va_arg(va,void *); - sipWrapperType *wt = va_arg(va, sipWrapperType *); - PyObject *xfer = va_arg(va, PyObject *); - - el = sip_api_convert_from_new_instance(p, wt, xfer); - } - - break; - - case 'C': - { - void *p = va_arg(va,void *); - sipWrapperType *wt = va_arg(va, sipWrapperType *); - PyObject *xfer = va_arg(va, PyObject *); - - el = sip_api_convert_from_instance(p, wt, xfer); - } - - break; - - case 'D': - { - void *p = va_arg(va, void *); - const sipMappedType *mt = va_arg(va, const sipMappedType *); - PyObject *xfer = va_arg(va, PyObject *); - - el = sip_api_convert_from_mapped_type(p, mt, xfer); - } - - break; - - case 'M': - case 'O': - { - void *sipCpp = va_arg(va,void *); - sipWrapperType *wt = va_arg(va,sipWrapperType *); - - el = sip_api_convert_from_instance(sipCpp,wt,NULL); - } - - break; - - case 'N': - case 'P': - { - void *sipCpp = va_arg(va,void *); - sipWrapperType *wt = va_arg(va,sipWrapperType *); - - el = sip_api_convert_from_new_instance(sipCpp,wt,NULL); - } - - break; - - case 'R': - el = va_arg(va,PyObject *); - break; - - case 'S': - el = va_arg(va,PyObject *); - Py_INCREF(el); - break; - - case 'T': - { - void *sipCpp = va_arg(va,void *); - sipConvertFromFunc func = va_arg(va,sipConvertFromFunc); - - el = func(sipCpp, NULL); - } - - 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; - va_list va; - - va_start(va,fmt); - - /* Basic validation of the format string. */ - - if (*fmt == '(') - { - char *ep; - - if ((ep = strchr(fmt,')')) == NULL || ep[1] != '\0') - { - PyErr_Format(PyExc_SystemError, "sipParseResult(): invalid format string \"%s\"", fmt); - rc = -1; - } - else - { - tupsz = ep - ++fmt; - - if (tupsz >= 0 && (!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 'a': - { - char **p = va_arg(va, char **); - int *szp = va_arg(va, int *); - - if (parseCharArray(arg, p, szp) < 0) - invalid = TRUE; - } - - break; - - case 'A': -#if defined(HAVE_WCHAR_H) - { - wchar_t **p = va_arg(va, wchar_t **); - int *szp = va_arg(va, int *); - - if (parseWCharArray(arg, p, szp) < 0) - invalid = TRUE; - } -#else - raiseNoWChar(); - invalid = TRUE; -#endif - - break; - - case 'b': - { - int v = PyInt_AsLong(arg); - - if (PyErr_Occurred()) - invalid = TRUE; - else - sipSetBool(va_arg(va,void *),v); - } - - break; - - case 'c': - { - char *p = va_arg(va, char *); - - if (parseChar(arg, p) < 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': - { - int v = PyInt_AsLong(arg); - - if (PyErr_Occurred()) - invalid = TRUE; - else - *va_arg(va,int *) = v; - } - - break; - - case 'E': - { - PyTypeObject *et = va_arg(va, PyTypeObject *); - int *p = va_arg(va, int *); - - if (PyObject_TypeCheck(arg, et)) - *p = PyInt_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 = PyInt_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 'i': - { - int v = PyInt_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': - { - char **p = va_arg(va, char **); - - if (parseCharString(arg, p) < 0) - invalid = TRUE; - } - - 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': - { - 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 & FORMAT_NO_STATE) - state = NULL; - else - state = va_arg(va, int *); - - cpp = va_arg(va, void **); - - *cpp = sip_api_force_convert_to_instance(arg, type, (flags & FORMAT_FACTORY ? arg : NULL), (flags & FORMAT_DEREF ? SIP_NOT_NONE : 0), state, &iserr); - - if (iserr) - invalid = TRUE; - } - } - - break; - - case 'D': - { - if (*fmt == '\0') - invalid = TRUE; - else - { - int flags = *fmt++ - '0'; - int iserr = FALSE; - const sipMappedType *mt; - void **cpp; - int *state; - - mt = va_arg(va, const sipMappedType *); - - if (flags & FORMAT_NO_STATE) - state = NULL; - else - state = va_arg(va, int *); - - cpp = va_arg(va, void **); - - *cpp = sip_api_force_convert_to_mapped_type(arg, mt, (flags & FORMAT_FACTORY ? arg : NULL), (flags & FORMAT_DEREF ? SIP_NOT_NONE : 0), state, &iserr); - - if (iserr) - invalid = TRUE; - } - } - - break; - - case 'L': - { - sipForceConvertToFunc func = va_arg(va,sipForceConvertToFunc); - void **sipCpp = va_arg(va,void **); - int iserr = FALSE; - - *sipCpp = func(arg,&iserr); - - if (iserr) - invalid = TRUE; - } - - break; - - case 'M': - { - sipForceConvertToFunc func = va_arg(va,sipForceConvertToFunc); - void **sipCpp = va_arg(va,void **); - int iserr = FALSE; - - *sipCpp = func(arg,&iserr); - - if (iserr || *sipCpp == NULL) - invalid = TRUE; - } - - 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(int *argsParsedp, PyObject *sipArgs, - const char *fmt, ...) -{ - int valid, nrargs, selfarg; - sipWrapper *self; - PyObject *single_arg; - va_list va; - - /* Previous sticky errors stop subsequent parses. */ - if (*argsParsedp & PARSE_STICKY) - return 0; - - /* See if we are parsing a tuple or a single argument. */ - if (PyTuple_Check(sipArgs)) - { - Py_INCREF(sipArgs); - nrargs = PyTuple_GET_SIZE(sipArgs); - } - else if ((single_arg = PyTuple_New(1)) != NULL) - { - Py_INCREF(sipArgs); - PyTuple_SET_ITEM(single_arg,0,sipArgs); - - sipArgs = single_arg; - nrargs = 1; - } - else - return 0; - - /* - * The first pass checks all the types and does conversions that are - * cheap and have no side effects. - */ - va_start(va,fmt); - valid = parsePass1(&self,&selfarg,&nrargs,sipArgs,fmt,va); - va_end(va); - - if (valid != PARSE_OK) - { - int pvalid, pnrargs; - - /* - * Use this error if there was no previous error, or if we - * have parsed more arguments this time, or if the previous - * error was that there were too many arguments. - */ - pvalid = (*argsParsedp & PARSE_MASK); - pnrargs = (*argsParsedp & ~PARSE_MASK); - - if (pvalid == PARSE_OK || pnrargs < nrargs || - (pnrargs == nrargs && pvalid == PARSE_MANY)) - *argsParsedp = valid | nrargs; - - Py_DECREF(sipArgs); - - return 0; - } - - /* - * The second pass does any remaining conversions now that we know we - * have the right signature. - */ - va_start(va,fmt); - valid = parsePass2(self,selfarg,nrargs,sipArgs,fmt,va); - va_end(va); - - if (valid != PARSE_OK) - { - *argsParsedp = valid | PARSE_STICKY; - - Py_DECREF(sipArgs); - - return 0; - } - - *argsParsedp = nrargs; - - Py_DECREF(sipArgs); - - return 1; -} - - -/* - * Parse a pair of arguments to a C/C++ function without any side effects. - */ -static int sip_api_parse_pair(int *argsParsedp, PyObject *sipArg0, - PyObject *sipArg1, const char *fmt, ...) -{ - int valid, nrargs, selfarg; - sipWrapper *self; - PyObject *args; - va_list va; - - /* Previous sticky errors stop subsequent parses. */ - if (*argsParsedp & PARSE_STICKY) - return 0; - - if ((args = PyTuple_New(2)) == NULL) - return 0; - - Py_INCREF(sipArg0); - PyTuple_SET_ITEM(args, 0, sipArg0); - - Py_INCREF(sipArg1); - PyTuple_SET_ITEM(args, 1, sipArg1); - - nrargs = 2; - - /* - * The first pass checks all the types and does conversions that are - * cheap and have no side effects. - */ - va_start(va,fmt); - valid = parsePass1(&self,&selfarg,&nrargs,args,fmt,va); - va_end(va); - - if (valid != PARSE_OK) - { - int pvalid, pnrargs; - - /* - * Use this error if there was no previous error, or if we - * have parsed more arguments this time, or if the previous - * error was that there were too many arguments. - */ - pvalid = (*argsParsedp & PARSE_MASK); - pnrargs = (*argsParsedp & ~PARSE_MASK); - - if (pvalid == PARSE_OK || pnrargs < nrargs || - (pnrargs == nrargs && pvalid == PARSE_MANY)) - *argsParsedp = valid | nrargs; - - Py_DECREF(args); - - return 0; - } - - /* - * The second pass does any remaining conversions now that we know we - * have the right signature. - */ - va_start(va,fmt); - valid = parsePass2(self,selfarg,nrargs,args,fmt,va); - va_end(va); - - if (valid != PARSE_OK) - { - *argsParsedp = valid | PARSE_STICKY; - - Py_DECREF(args); - - return 0; - } - - *argsParsedp = nrargs; - - Py_DECREF(args); - - return 1; -} - - -/* - * First pass of the argument parse, converting those that can be done so - * without any side effects. Return PARSE_OK if the arguments matched. - */ -static int parsePass1(sipWrapper **selfp, int *selfargp, int *argsParsedp, - PyObject *sipArgs, const char *fmt, va_list va) -{ - int valid, compulsory, nrargs, argnr, nrparsed; - - valid = PARSE_OK; - nrargs = *argsParsedp; - nrparsed = 0; - compulsory = TRUE; - argnr = 0; - - /* - * 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; - sipWrapperType *type; - - self = *va_arg(va,PyObject **); - type = va_arg(va,sipWrapperType *); - va_arg(va,void **); - - if (self == NULL) - { - if ((valid = getSelfFromArgs(type,sipArgs,argnr,selfp)) != PARSE_OK) - break; - - *selfargp = TRUE; - ++nrparsed; - ++argnr; - } - else - *selfp = (sipWrapper *)self; - - break; - } - - case 'C': - *selfp = (sipWrapper *)va_arg(va,PyObject *); - break; - - default: - --fmt; - } - - /* Now handle the remaining arguments. */ - while (valid == PARSE_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') - { - /* Invalid if there are still arguments. */ - if (argnr < nrargs) - valid = PARSE_MANY; - - break; - } - - /* See if we have run out of arguments. */ - - if (argnr == nrargs) - { - /* - * It is an error if we are still expecting compulsory - * arguments unless the current argume is an ellipsis. - */ - if (ch != 'W' && ch != '\0' && compulsory) - valid = PARSE_FEW; - - break; - } - - /* Get the next argument. */ - arg = PyTuple_GET_ITEM(sipArgs,argnr); - ++argnr; - - switch (ch) - { - case 'W': - /* Ellipsis. */ - break; - - case 's': - { - /* String or None. */ - - char **p = va_arg(va, char **); - - if (parseCharString(arg, p) < 0) - valid = PARSE_TYPE; - - break; - } - - case 'x': -#if defined(HAVE_WCHAR_H) - { - /* Wide string or None. */ - - wchar_t **p = va_arg(va, wchar_t **); - - if (parseWCharString(arg, p) < 0) - valid = PARSE_TYPE; - - break; - } -#else - raiseNoWChar(); - valid = PARSE_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 **); - - *sname = NULL; - *scall = NULL; - - if (PyString_Check(arg)) - { - char *s = PyString_AS_STRING(arg); - - if (*s == '1' || *s == '2' || *s == '9') - *sname = s; - else - valid = PARSE_TYPE; - } - else if (PyCallable_Check(arg)) - *scall = arg; - else if (arg != Py_None) - valid = PARSE_TYPE; - - break; - } - - case 'S': - { - /* Slot name, return the name. */ - - if (PyString_Check(arg)) - { - char *s = PyString_AS_STRING(arg); - - if (*s == '1' || *s == '2' || *s == '9') - *va_arg(va,char **) = s; - else - valid = PARSE_TYPE; - } - else - valid = PARSE_TYPE; - - break; - } - - case 'G': - { - /* Signal name, return the name. */ - - if (PyString_Check(arg)) - { - char *s = PyString_AS_STRING(arg); - - if (*s == '2' || *s == '9') - *va_arg(va,char **) = s; - else - valid = PARSE_TYPE; - } - else - valid = PARSE_TYPE; - - break; - } - - case 'J': - { - /* Class instance. */ - - if (*fmt == '\0') - valid = PARSE_FORMAT; - else - { - int flags = *fmt++ - '0'; - sipWrapperType *type; - int iflgs = 0; - - type = va_arg(va,sipWrapperType *); - va_arg(va,void **); - - if (flags & FORMAT_DEREF) - iflgs |= SIP_NOT_NONE; - - if (flags & (FORMAT_GET_WRAPPER|FORMAT_TRANSFER_THIS)) - va_arg(va,PyObject **); - - if (flags & FORMAT_NO_CONVERTORS) - iflgs |= SIP_NO_CONVERTORS; - else - va_arg(va, int *); - - if (!sip_api_can_convert_to_instance(arg, type, iflgs)) - valid = PARSE_TYPE; - } - - break; - } - - case 'M': - { - /* Mapped type instance. */ - - if (*fmt == '\0') - valid = PARSE_FORMAT; - else - { - int flags = *fmt++ - '0'; - sipMappedType *mt; - int iflgs = 0; - - mt = va_arg(va, sipMappedType *); - va_arg(va, void **); - va_arg(va, int *); - - if (flags & FORMAT_DEREF) - iflgs |= SIP_NOT_NONE; - - if (!sip_api_can_convert_to_mapped_type(arg, mt, iflgs)) - valid = PARSE_TYPE; - } - - break; - } - - - case 'N': - { - /* Python object of given type or None. */ - - PyTypeObject *type = va_arg(va,PyTypeObject *); - PyObject **p = va_arg(va,PyObject **); - - if (arg == Py_None || PyObject_TypeCheck(arg,type)) - *p = arg; - else - valid = PARSE_TYPE; - - break; - } - - case 'P': - { - /* - * Python object of any type with a - * sub-format. - */ - - *va_arg(va,PyObject **) = arg; - - /* Skip the sub-format. */ - if (*fmt++ == '\0') - valid = PARSE_FORMAT; - - break; - } - - case 'T': - { - /* Python object of given type. */ - - PyTypeObject *type = va_arg(va,PyTypeObject *); - PyObject **p = va_arg(va,PyObject **); - - if (PyObject_TypeCheck(arg,type)) - *p = arg; - else - valid = PARSE_TYPE; - - break; - } - - case 'R': - { - /* Sub-class of TQObject. */ - - if (sipQtSupport == NULL || !PyObject_TypeCheck(arg, (PyTypeObject *)sipQObjectClass)) - valid = PARSE_TYPE; - else - *va_arg(va,PyObject **) = arg; - - break; - } - - case 'F': - { - /* Python callable object. */ - - if (PyCallable_Check(arg)) - *va_arg(va,PyObject **) = arg; - else - valid = PARSE_TYPE; - - break; - } - - case 'H': - { - /* Python callable object or None. */ - - if (arg == Py_None || PyCallable_Check(arg)) - *va_arg(va,PyObject **) = arg; - else - valid = PARSE_TYPE; - - break; - } - - case 'q': - { - /* Qt receiver to connect. */ - - va_arg(va,char *); - va_arg(va,void **); - va_arg(va,const char **); - - if (sipQtSupport == NULL || !PyObject_TypeCheck(arg, (PyTypeObject *)sipQObjectClass)) - valid = PARSE_TYPE; - - break; - } - - case 'Q': - { - /* Qt receiver to disconnect. */ - - va_arg(va,char *); - va_arg(va,void **); - va_arg(va,const char **); - - if (sipQtSupport == NULL || !PyObject_TypeCheck(arg, (PyTypeObject *)sipQObjectClass)) - valid = PARSE_TYPE; - - break; - } - - case 'y': - { - /* Python slot to connect. */ - - va_arg(va,char *); - va_arg(va,void **); - va_arg(va,const char **); - - if (sipQtSupport == NULL || !PyCallable_Check(arg)) - valid = PARSE_TYPE; - - break; - } - - case 'Y': - { - /* Python slot to disconnect. */ - - va_arg(va,char *); - va_arg(va,void **); - va_arg(va,const char **); - - if (sipQtSupport == NULL || !PyCallable_Check(arg)) - valid = PARSE_TYPE; - - break; - } - - case 'a': - { - /* Char array or None. */ - - char **p = va_arg(va, char **); - int *szp = va_arg(va, int *); - - if (parseCharArray(arg, p, szp) < 0) - valid = PARSE_TYPE; - - break; - } - - case 'A': -#if defined(HAVE_WCHAR_H) - { - /* Wide char array or None. */ - - wchar_t **p = va_arg(va, wchar_t **); - int *szp = va_arg(va, int *); - - if (parseWCharArray(arg, p, szp) < 0) - valid = PARSE_TYPE; - - break; - } -#else - raiseNoWChar(); - valid = PARSE_RAISED; - break -#endif - - case 'c': - { - /* Character. */ - - char *p = va_arg(va, char *); - - if (parseChar(arg, p) < 0) - valid = PARSE_TYPE; - - break; - } - - case 'w': -#if defined(HAVE_WCHAR_H) - { - /* Wide character. */ - - wchar_t *p = va_arg(va, wchar_t *); - - if (parseWChar(arg, p) < 0) - valid = PARSE_TYPE; - - break; - } -#else - raiseNoWChar(); - valid = PARSE_RAISED; - break -#endif - - case 'b': - { - /* Bool. */ - - int v = PyInt_AsLong(arg); - - if (PyErr_Occurred()) - valid = PARSE_TYPE; - else - sipSetBool(va_arg(va,void *),v); - - break; - } - - case 'e': - { - /* Anonymous enum. */ - - int v = PyInt_AsLong(arg); - - if (PyErr_Occurred()) - valid = PARSE_TYPE; - else - *va_arg(va,int *) = v; - - break; - } - - case 'E': - { - /* Named enum. */ - - PyTypeObject *et = va_arg(va, PyTypeObject *); - - va_arg(va, int *); - - if (!PyObject_TypeCheck(arg, et)) - valid = PARSE_TYPE; - } - - break; - - case 'i': - { - /* Integer. */ - - int v = PyInt_AsLong(arg); - - if (PyErr_Occurred()) - valid = PARSE_TYPE; - else - *va_arg(va,int *) = v; - - break; - } - - case 'u': - { - /* Unsigned integer. */ - - unsigned v = sip_api_long_as_unsigned_long(arg); - - if (PyErr_Occurred()) - valid = PARSE_TYPE; - else - *va_arg(va, unsigned *) = v; - - break; - } - - case 'h': - { - /* Short integer. */ - - short v = PyInt_AsLong(arg); - - if (PyErr_Occurred()) - valid = PARSE_TYPE; - else - *va_arg(va,short *) = v; - - break; - } - - case 't': - { - /* Unsigned short integer. */ - - unsigned short v = sip_api_long_as_unsigned_long(arg); - - if (PyErr_Occurred()) - valid = PARSE_TYPE; - else - *va_arg(va, unsigned short *) = v; - - break; - } - - case 'l': - { - /* Long integer. */ - - long v = PyLong_AsLong(arg); - - if (PyErr_Occurred()) - valid = PARSE_TYPE; - else - *va_arg(va,long *) = v; - - break; - } - - case 'm': - { - /* Unsigned long integer. */ - - unsigned long v = sip_api_long_as_unsigned_long(arg); - - if (PyErr_Occurred()) - valid = PARSE_TYPE; - else - *va_arg(va, unsigned long *) = v; - - break; - } - - case 'n': - { - /* Long long integer. */ - -#if defined(HAVE_LONG_LONG) - PY_LONG_LONG v = PyLong_AsLongLong(arg); -#else - long v = PyLong_AsLong(arg); -#endif - - if (PyErr_Occurred()) - valid = PARSE_TYPE; - else -#if defined(HAVE_LONG_LONG) - *va_arg(va, PY_LONG_LONG *) = v; -#else - *va_arg(va, long *) = v; -#endif - - break; - } - - case 'o': - { - /* Unsigned long long integer. */ - -#if defined(HAVE_LONG_LONG) - unsigned PY_LONG_LONG v = PyLong_AsUnsignedLongLong(arg); -#else - unsigned long v = PyLong_AsUnsignedLong(arg); -#endif - - if (PyErr_Occurred()) - valid = PARSE_TYPE; - else -#if defined(HAVE_LONG_LONG) - *va_arg(va, unsigned PY_LONG_LONG *) = v; -#else - *va_arg(va, unsigned long *) = v; -#endif - - break; - } - - case 'f': - { - /* Float. */ - - double v = PyFloat_AsDouble(arg); - - if (PyErr_Occurred()) - valid = PARSE_TYPE; - else - *va_arg(va,float *) = (float)v; - - break; - } - - case 'X': - { - /* Constrained (ie. exact) types. */ - - switch (*fmt++) - { - case 'b': - { - /* Boolean. */ - - if (PyBool_Check(arg)) - sipSetBool(va_arg(va,void *),(arg == Py_True)); - else - valid = PARSE_TYPE; - - break; - } - - case 'd': - { - /* Double float. */ - - if (PyFloat_Check(arg)) - *va_arg(va,double *) = PyFloat_AS_DOUBLE(arg); - else - valid = PARSE_TYPE; - - break; - } - - case 'f': - { - /* Float. */ - - if (PyFloat_Check(arg)) - *va_arg(va,float *) = (float)PyFloat_AS_DOUBLE(arg); - else - valid = PARSE_TYPE; - - break; - } - - case 'i': - { - /* Integer. */ - - if (PyInt_Check(arg)) - *va_arg(va,int *) = PyInt_AS_LONG(arg); - else - valid = PARSE_TYPE; - - break; - } - - default: - valid = PARSE_FORMAT; - } - - break; - } - - case 'd': - { - /* Double float. */ - - double v = PyFloat_AsDouble(arg); - - if (PyErr_Occurred()) - valid = PARSE_TYPE; - else - *va_arg(va,double *) = v; - - break; - } - - case 'v': - { - /* Void pointer. */ - - void *v = sip_api_convert_to_void_ptr(arg); - - if (PyErr_Occurred()) - valid = PARSE_TYPE; - else - *va_arg(va,void **) = v; - - break; - } - - default: - valid = PARSE_FORMAT; - } - - if (valid == PARSE_OK) - { - if (ch == 'W') - { - /* - * An ellipsis matches everything and ends the - * parse. - */ - nrparsed = nrargs; - break; - } - - ++nrparsed; - } - } - - *argsParsedp = nrparsed; - - return valid; -} - - -/* - * Second pass of the argument parse, converting the remaining ones that might - * have side effects. Return PARSE_OK if there was no error. - */ -static int parsePass2(sipWrapper *self, int selfarg, int nrargs, - PyObject *sipArgs, const char *fmt, va_list va) -{ - int a, valid; - - valid = PARSE_OK; - - /* Handle the converions of "self" first. */ - switch (*fmt++) - { - case 'B': - { - /* - * The address of a C++ instance when calling one of - * its public methods. - */ - - sipWrapperType *type; - void **p; - - *va_arg(va,PyObject **) = (PyObject *)self; - type = va_arg(va,sipWrapperType *); - p = va_arg(va,void **); - - if ((*p = sip_api_get_cpp_ptr(self,type)) == NULL) - valid = PARSE_RAISED; - - break; - } - - case 'p': - { - /* - * The address of a C++ instance when calling one of - * its protected methods. - */ - - void **p; - - *va_arg(va,PyObject **) = (PyObject *)self; - va_arg(va,sipWrapperType *); - p = va_arg(va,void **); - - if ((*p = sip_api_get_complex_cpp_ptr(self)) == NULL) - valid = PARSE_RAISED; - - break; - } - - case 'C': - va_arg(va,PyObject *); - break; - - default: - --fmt; - } - - for (a = (selfarg ? 1 : 0); a < nrargs && *fmt != 'W' && valid == PARSE_OK; ++a) - { - char ch; - PyObject *arg = PyTuple_GET_ITEM(sipArgs,a); - - /* Skip the optional character. */ - if ((ch = *fmt++) == '|') - ch = *fmt++; - - /* - * Do the outstanding conversions. For most types it has - * already been done, so we are just skipping the parameters. - */ - switch (ch) - { - 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 ((*rx = sip_api_convert_rx(self,sig,arg,*slot,slot)) == NULL) - valid = PARSE_RAISED; - - 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 **); - - *rx = sipGetRx(self,sig,arg,*slot,slot); - 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 ((*rx = sip_api_convert_rx(self,sig,arg,NULL,slot)) == NULL) - valid = PARSE_RAISED; - - 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 **); - - *rx = sipGetRx(self,sig,arg,NULL,slot); - break; - } - - case 'J': - { - /* Class instance. */ - - int flags = *fmt++ - '0'; - sipWrapperType *type; - void **p; - int iflgs = 0; - int iserr = FALSE; - int *state; - PyObject *xfer, **wrapper; - - type = va_arg(va,sipWrapperType *); - p = va_arg(va,void **); - - if (flags & FORMAT_TRANSFER) - xfer = (self ? (PyObject *)self : arg); - else if (flags & FORMAT_TRANSFER_BACK) - xfer = Py_None; - else - xfer = NULL; - - if (flags & FORMAT_DEREF) - iflgs |= SIP_NOT_NONE; - - if (flags & (FORMAT_GET_WRAPPER|FORMAT_TRANSFER_THIS)) - wrapper = va_arg(va, PyObject **); - - if (flags & FORMAT_NO_CONVERTORS) - { - iflgs |= SIP_NO_CONVERTORS; - state = NULL; - } - else - state = va_arg(va, int *); - - *p = sip_api_convert_to_instance(arg, type, xfer, iflgs, state, &iserr); - - if (iserr) - valid = PARSE_RAISED; - - if (flags & FORMAT_GET_WRAPPER) - *wrapper = (*p != NULL ? arg : NULL); - else if (flags & FORMAT_TRANSFER_THIS && *p != NULL) - *wrapper = arg; - - break; - } - - case 'M': - { - /* Mapped type instance. */ - - int flags = *fmt++ - '0'; - sipMappedType *mt; - void **p; - int iflgs = 0; - int iserr = FALSE; - int *state; - PyObject *xfer; - - mt = va_arg(va, sipMappedType *); - p = va_arg(va, void **); - state = va_arg(va, int *); - - if (flags & FORMAT_TRANSFER) - xfer = (self ? (PyObject *)self : arg); - else if (flags & FORMAT_TRANSFER_BACK) - xfer = Py_None; - else - xfer = NULL; - - if (flags & FORMAT_DEREF) - iflgs |= SIP_NOT_NONE; - - *p = sip_api_convert_to_mapped_type(arg, mt, xfer, iflgs, state, &iserr); - - if (iserr) - valid = PARSE_RAISED; - - break; - } - - case 'P': - { - /* - * Python object of any type with a - * sub-format. - */ - - PyObject **p = va_arg(va,PyObject **); - int flags = *fmt++ - '0'; - - if (flags & FORMAT_TRANSFER) - { - Py_XINCREF(*p); - } - else if (flags & FORMAT_TRANSFER_BACK) - { - Py_XDECREF(*p); - } - - break; - } - - case 'X': - { - /* Constrained (ie. exact) type. */ - - ++fmt; - va_arg(va,void *); - - break; - } - - - case 'E': - { - /* Named enum. */ - - int *p; - - va_arg(va, PyTypeObject *); - p = va_arg(va, int *); - - *p = PyInt_AsLong(arg); - - break; - } - - /* - * Every other argument is a pointer and only differ in how - * many there are. - */ - case 'N': - case 'T': - case 'a': - case 'A': - va_arg(va,void *); - - /* Drop through. */ - - default: - va_arg(va,void *); - } - } - - /* Handle any ellipsis argument. */ - if (*fmt == 'W' && valid == PARSE_OK) - { - PyObject *al; - - /* Create a tuple for any remaining arguments. */ - if ((al = PyTuple_New(nrargs - a)) != NULL) - { - int da = 0; - - while (a < nrargs) - { - 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; - } - else - valid = PARSE_RAISED; - } - - return valid; -} - - -/* - * Carry out actions common to all ctors. - */ -static void sip_api_common_ctor(sipMethodCache *cache,int nrmeths) -{ - /* This is thread safe. */ - while (nrmeths-- > 0) - cache++->mcflags = 0; -} - - -/* - * Carry out actions common to all dtors. - */ -static void sip_api_common_dtor(sipWrapper *sipSelf) -{ - if (sipSelf != NULL && sipInterpreter != NULL) - { - SIP_BLOCK_THREADS - - callPyDtor(sipSelf); - - 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 - removeFromParent(sipSelf); - - SIP_UNBLOCK_THREADS - } -} - - -/* - * Call self.__dtor__() if it is implemented. - */ -static void callPyDtor(sipWrapper *self) -{ - sip_gilstate_t sipGILState; - sipMethodCache pymc; - PyObject *meth; - - /* No need to cache the method, it will only be called once. */ - pymc.mcflags = 0; - 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); - - SIP_RELEASE_GIL(sipGILState); - } -} - - -/* - * Add a wrapper to it's parent owner if it has one. The wrapper must not - * currently have a parent and, therefore, no siblings. - */ -static void addToParent(sipWrapper *self, sipWrapper *owner) -{ - if (owner != NULL) - { - 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(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(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; -} - - -/* - * Create and return a single type object. - */ -static sipWrapperType *createType(sipExportedModuleDef *client, - sipTypeDef *type, PyObject *mod_dict) -{ - PyObject *name, *bases, *typedict, *args, *dict; - sipEncodedClassDef *sup; - sipWrapperType *wt; - - /* Create an object corresponding to the type name. */ - if ((name = getBaseNameObject(type->td_name)) == NULL) - goto reterr; - - /* Create the tuple of super types. */ - if ((sup = type->td_supers) == NULL) - { - static PyObject *nobases = NULL; - - if (nobases == NULL && (nobases = Py_BuildValue("(O)",&sipWrapper_Type)) == NULL) - goto relname; - - Py_INCREF(nobases); - bases = nobases; - } - else - { - int i, nrsupers = 0; - - do - ++nrsupers; - while (!sup++->sc_flag); - - if ((bases = PyTuple_New(nrsupers)) == NULL) - goto relname; - - for (sup = type->td_supers, i = 0; i < nrsupers; ++i, ++sup) - { - PyObject *st = (PyObject *)getClassType(sup, client); - - Py_INCREF(st); - PyTuple_SET_ITEM(bases,i,st); - } - } - - /* Create the type dictionary. */ - if ((typedict = createTypeDict(client->em_nameobj)) == NULL) - goto relbases; - - /* Initialise the rest of the type and pass it via the back door. */ - type->td_module = client; - currentType = type; - - /* Create the type by calling the metatype. */ - if ((args = Py_BuildValue("OOO",name,bases,typedict)) == NULL) - goto reldict; - - if ((wt = (sipWrapperType *)PyObject_Call((PyObject *)&sipWrapperType_Type,args,NULL)) == NULL) - goto relargs; - - /* Get the dictionary into which the type will be placed. */ - if (type->td_scope.sc_flag) - dict = mod_dict; - else - dict = ((PyTypeObject *)getClassType(&type->td_scope, client))->tp_dict; - - /* Add the type to the "parent" dictionary. */ - if (PyDict_SetItem(dict,name,(PyObject *)wt) < 0) - goto reltype; - - /* We can now release our references. */ - Py_DECREF(args); - Py_DECREF(typedict); - Py_DECREF(bases); - Py_DECREF(name); - - return wt; - - /* Unwind after an error. */ - -reltype: - Py_DECREF((PyObject *)wt); - -relargs: - Py_DECREF(args); - -reldict: - Py_DECREF(typedict); - -relbases: - Py_DECREF(bases); - -relname: - Py_DECREF(name); - -reterr: - return NULL; -} - - -/* - * Create and return an enum type object. - */ -static PyTypeObject *createEnum(sipExportedModuleDef *client, sipEnumDef *ed, - PyObject *mod_dict) -{ - static PyObject *bases = NULL; - PyObject *name, *typedict, *args, *dict; - PyTypeObject *et; - - /* Get the module and dictionary into which the type will be placed. */ - if (ed->e_scope < 0) - dict = mod_dict; - else - dict = ((PyTypeObject *)client->em_types[ed->e_scope])->tp_dict; - - /* Create the base type tuple if it hasn't already been done. */ - if (bases == NULL && (bases = Py_BuildValue("(O)",&PyInt_Type)) == NULL) - goto reterr; - - /* Create an object corresponding to the type name. */ - if ((name = getBaseNameObject(ed->e_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 ((args = Py_BuildValue("OOO",name,bases,typedict)) == NULL) - goto reldict; - - if ((et = (PyTypeObject *)PyObject_Call((PyObject *)&PyType_Type,args,NULL)) == NULL) - goto relargs; - - /* Initialise any slots. */ - if (ed->e_pyslots != NULL) - initSlots(et, et->tp_as_number, et->tp_as_sequence, et->tp_as_mapping, ed->e_pyslots, TRUE); - - /* Add the type to the "parent" dictionary. */ - if (PyDict_SetItem(dict,name,(PyObject *)et) < 0) - goto reltype; - - /* We can now release our references. */ - Py_DECREF(args); - Py_DECREF(typedict); - Py_DECREF(name); - - return et; - - /* Unwind after an error. */ - -reltype: - Py_DECREF((PyObject *)et); - -relargs: - Py_DECREF(args); - -reldict: - Py_DECREF(typedict); - -relname: - Py_DECREF(name); - -reterr: - return NULL; -} - - -/* - * Return a pointer to the basename of a Python "pathname". - */ -static const char *getBaseName(const char *name) -{ - const char *bn; - - if ((bn = strrchr(name, '.')) != NULL) - ++bn; - else - bn = name; - - return bn; -} - - -/* - * Create a Python object corresponding to the basename of a Python "pathname". - */ -static PyObject *getBaseNameObject(const char *name) -{ - return PyString_FromString(getBaseName(name)); -} - - -/* - * Create a type dictionary for dynamic type being created in the module with - * the specified name. - */ -static PyObject *createTypeDict(PyObject *mname) -{ - static PyObject *proto = NULL; - static PyObject *mstr = NULL; - PyObject *dict; - - /* Create a prototype dictionary. */ - if (proto == NULL) - { - if ((proto = PyDict_New()) == NULL) - return NULL; - - /* - * These tell pickle that SIP generated classes can't be - * pickled. - */ - if (PyDict_SetItemString(proto, "__reduce_ex__", Py_None) < 0 || - PyDict_SetItemString(proto, "__reduce__", Py_None) < 0) - { - Py_DECREF(proto); - proto = NULL; - - return NULL; - } - } - - /* Create an object for "__module__". */ - if (mstr == NULL && (mstr = PyString_FromString("__module__")) == NULL) - return NULL; - - if ((dict = PyDict_Copy(proto)) == 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; -} - - -/* - * Add a set of static instances to a dictionary. - */ -static int addInstances(PyObject *dict,sipInstancesDef *id) -{ - if (id->id_class != NULL && addClassInstances(dict,id->id_class) < 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; - - if (id->id_enum != NULL && addEnumInstances(dict,id->id_enum) < 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(sipWrapperType *type, PyObject *args, int argnr, - sipWrapper **selfp) -{ - PyObject *self; - - /* Get self from the argument tuple. */ - - if (argnr >= PyTuple_GET_SIZE(args)) - return PARSE_UNBOUND; - - self = PyTuple_GET_ITEM(args, argnr); - - if (!PyObject_TypeCheck(self, (PyTypeObject *)type)) - return PARSE_UNBOUND; - - *selfp = (sipWrapper *)self; - - return PARSE_OK; -} - - -/* - * Handle the result of a call to the class/instance setattro methods. - */ -static int handleSetLazyAttr(PyObject *nameobj,PyObject *valobj, - sipWrapperType *wt,sipWrapper *w) -{ - char *name; - PyMethodDef *pmd, *vmd; - sipEnumMemberDef *enm; - - /* See if it was a lazy attribute. */ - if ((name = PyString_AsString(nameobj)) == NULL) - return -1; - - pmd = NULL; - enm = NULL; - vmd = NULL; - - findLazyAttr(wt,name,&pmd,&enm,&vmd,NULL); - - if (vmd != NULL) - { - if (valobj == NULL) - { - PyErr_Format(PyExc_ValueError,"%s.%s cannot be deleted",wt->type->td_name,name); - - return -1; - } - - if ((vmd->ml_flags & METH_STATIC) != 0 || w != NULL) - { - PyObject *res; - - if ((res = (*vmd->ml_meth)((PyObject *)w,valobj)) == NULL) - return -1; - - /* Ignore the result (which should be Py_None). */ - Py_DECREF(res); - - return 0; - } - - PyErr_SetObject(PyExc_AttributeError,nameobj); - - return -1; - } - - /* It isn't a variable. */ - return 1; -} - - -/* - * Handle the result of a call to the class/instance getattro methods. - */ -static PyObject *handleGetLazyAttr(PyObject *nameobj,sipWrapperType *wt, - sipWrapper *w) -{ - char *name; - PyMethodDef *pmd, *vmd; - sipEnumMemberDef *enm; - sipTypeDef *in; - - /* If it was an error, propagate it. */ - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) - return NULL; - - PyErr_Clear(); - - /* See if it was a lazy attribute. */ - if ((name = PyString_AsString(nameobj)) == NULL) - return NULL; - - pmd = NULL; - enm = NULL; - vmd = NULL; - - findLazyAttr(wt,name,&pmd,&enm,&vmd,&in); - - if (pmd != NULL) - return PyCFunction_New(pmd,(PyObject *)w); - - if (enm != NULL) - { - PyObject *attr; - - /* - * Convert the value to an object. Note that we cannot cache - * it in the type dictionary because a sub-type might have a - * lazy attribute of the same name. In this case (because we - * call the standard getattro code first) this one would be - * wrongly found in preference to the one in the sub-class. - * The example in PyQt is TQScrollView::ResizePolicy and - * TQListView::WidthMode both having a member called Manual. - * One way around this might be to cache them in a separate - * dictionary and search that before doing the binary search - * through the lazy enum table. - */ - if ((attr = createEnumMember(in, enm)) == NULL) - return NULL; - - return attr; - } - - if (vmd != NULL) - if ((vmd->ml_flags & METH_STATIC) != 0 || w != NULL) - return (*vmd->ml_meth)((PyObject *)w,NULL); - - PyErr_SetObject(PyExc_AttributeError,nameobj); - - return NULL; -} - - -/* - * Create a Python object for an enum member. - */ -static PyObject *createEnumMember(sipTypeDef *td, sipEnumMemberDef *enm) -{ - if (enm->em_enum < 0) - return PyInt_FromLong(enm->em_val); - - return sip_api_convert_from_named_enum(enm->em_val, td->td_module->em_enums[enm->em_enum]); -} - - -/* - * Create a Python object for a member of a named enum. - */ -PyObject *sip_api_convert_from_named_enum(int eval, PyTypeObject *et) -{ - PyObject *args, *mo; - - if ((args = Py_BuildValue("(i)", eval)) == NULL) - return NULL; - - mo = PyObject_Call((PyObject *)et, args, NULL); - - Py_DECREF(args); - - return mo; -} - - -/* - * Find definition for a lazy class attribute. - */ -static void findLazyAttr(sipWrapperType *wt,char *name,PyMethodDef **pmdp, - sipEnumMemberDef **enmp,PyMethodDef **vmdp, - sipTypeDef **in) -{ - sipTypeDef *td, *nsx; - sipEncodedClassDef *sup; - - /* The base type doesn't have any type information. */ - if ((td = wt->type) == NULL) - return; - - /* Search the possible linked list of namespace extenders. */ - nsx = td; - - do - { - /* Try the methods. */ - if (nsx->td_nrmethods > 0 && - (*pmdp = (PyMethodDef *)bsearch(name, nsx->td_methods, nsx->td_nrmethods, sizeof (PyMethodDef), compareMethodName)) != NULL) - return; - - /* Try the enum members. */ - if (nsx->td_nrenummembers > 0 && - (*enmp = (sipEnumMemberDef *)bsearch(name, nsx->td_enummembers, nsx->td_nrenummembers, sizeof (sipEnumMemberDef), compareEnumMemberName)) != NULL) - { - if (in != NULL) - *in = nsx; - - return; - } - - /* Try the variables. Note, these aren't sorted. */ - if (nsx->td_variables != NULL) - { - PyMethodDef *md; - - for (md = nsx->td_variables; md->ml_name != NULL; ++md) - if (strcmp(name, md->ml_name) == 0) - { - *vmdp = md; - return; - } - } - - nsx = nsx->td_nsextender; - } - while (nsx != NULL); - - /* Check the base classes. */ - if ((sup = td->td_supers) != NULL) - do - { - findLazyAttr(getClassType(sup, td->td_module), name, pmdp, enmp, vmdp, in); - - if (*pmdp != NULL || *enmp != NULL || *vmdp != NULL) - break; - } - while (!sup++->sc_flag); -} - - -/* - * The bsearch() helper function for searching a sorted method table. - */ -static int compareMethodName(const void *key,const void *el) -{ - return strcmp((const char *)key,((const PyMethodDef *)el)->ml_name); -} - - -/* - * The bsearch() helper function for searching a sorted enum member table. - */ -static int compareEnumMemberName(const void *key,const void *el) -{ - return strcmp((const char *)key,((const sipEnumMemberDef *)el)->em_name); -} - - -/* - * Report a function with invalid argument types. - */ -static void sip_api_no_function(int argsParsed, const char *func) -{ - badArgs(argsParsed,NULL,func); -} - - -/* - * Report a method/function/signal with invalid argument types. - */ -static void sip_api_no_method(int argsParsed, const char *classname, const char *method) -{ - badArgs(argsParsed,classname,method); -} - - -/* - * 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); -} - - -/* - * Handle error reporting for bad arguments to various things. - */ -static void badArgs(int argsParsed, const char *classname, const char *method) -{ - char *sep; - int nrparsed = argsParsed & ~PARSE_MASK; - - if (classname != NULL) - sep = "."; - else - { - classname = ""; - sep = ""; - } - - switch (argsParsed & PARSE_MASK) - { - case PARSE_FEW: - PyErr_Format(PyExc_TypeError,"insufficient number of arguments to %s%s%s()",classname,sep,method); - break; - - case PARSE_MANY: - PyErr_Format(PyExc_TypeError,"too many arguments to %s%s%s(), %d at most expected",classname,sep,method,nrparsed); - break; - - case PARSE_TYPE: - PyErr_Format(PyExc_TypeError,"argument %d of %s%s%s() has an invalid type",nrparsed + 1,classname,sep,method); - break; - - case PARSE_FORMAT: - PyErr_Format(PyExc_TypeError,"invalid format to sipParseArgs() from %s%s%s()",classname,sep,method); - break; - - case PARSE_UNBOUND: - PyErr_Format(PyExc_TypeError,"first argument of unbound method %s%s%s() must be a %s instance",classname,sep,method,classname); - break; - - case PARSE_RAISED: - /* It has already been taken care of. */ - - break; - - case PARSE_OK: - /* This is raised by a private re-implementation. */ - PyErr_Format(PyExc_AttributeError,"%s%s%s is a private method",classname,sep,method); - break; - } -} - - -/* - * 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", self->ob_type->tp_name, arg->ob_type->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, self->ob_type->tp_name, arg->ob_type->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 class variable with an unexpected type. - */ -static void sip_api_bad_set_type(const char *classname,const char *var) -{ - PyErr_Format(PyExc_TypeError,"invalid type for variable %s.%s",classname,var); -} - - -/* - * Report a Python member function with an unexpected return type. - */ -static void sip_api_bad_catcher_result(PyObject *method) -{ - const char *cname; - char *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 = PyString_AsString(((PyFunctionObject *)PyMethod_GET_FUNCTION(method))->func_name); - - if (mname == NULL) - return; - - cname = PyMethod_GET_SELF(method)->ob_type->tp_name; - - PyErr_Format(PyExc_TypeError,"invalid result type from %s.%s()",cname,mname); -} - - -/* - * Return the name of the class corresponding to a wrapper object. This comes - * with a reference. - */ -static PyObject *sip_api_class_name(PyObject *self) -{ - return PyString_FromString(self->ob_type->tp_name); -} - - -/* - * Return non-zero if the object is a C++ instance wrapper. - */ -int sip_api_wrapper_check(PyObject *o) -{ - return PyObject_TypeCheck(o,(PyTypeObject *)&sipWrapper_Type); -} - - -/* - * Return non-zero if the object is a C++ instance wrapper type. - */ -static int sipWrapperType_Check(PyObject *op) -{ - return PyObject_TypeCheck(op,(PyTypeObject *)&sipWrapperType_Type); -} - - -/* - * Transfer ownership of a class instance to Python from C/C++. - */ -static void sip_api_transfer_back(PyObject *self) -{ - if (self != NULL && sip_api_wrapper_check(self)) - { - sipWrapper *w = (sipWrapper *)self; - - if (sipCppHasRef(w)) - { - sipResetCppHasRef(w); - Py_DECREF(w); - } - else - removeFromParent(w); - - sipSetPyOwned(w); - } -} - - -/* - * 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 && sip_api_wrapper_check(self) && (owner == NULL || sip_api_wrapper_check(owner))) - { - sipWrapper *w = (sipWrapper *)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(w)) - sipResetCppHasRef(w); - else - { - Py_INCREF(self); - removeFromParent(w); - } - - addToParent(w, (sipWrapper *)owner); - - Py_DECREF(self); - - sipResetPyOwned(w); - } -} - - -/* - * Transfer ownership of a class instance from Python to C/C++, or vice versa. - * This is deprecated. - */ -static void sip_api_transfer(PyObject *self, int toCpp) -{ - if (toCpp) - sip_api_transfer_to(self, self); - else - sip_api_transfer_back(self); -} - - -/* - * 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 (licenseName == NULL && (licenseName = PyString_FromString("__license__")) == NULL) - return -1; - - if (licenseeName == NULL && (licenseeName = PyString_FromString("Licensee")) == NULL) - return -1; - - if (typeName == NULL && (typeName = PyString_FromString("Type")) == NULL) - return -1; - - if (timestampName == NULL && (timestampName = PyString_FromString("Timestamp")) == NULL) - return -1; - - if (signatureName == NULL && (signatureName = PyString_FromString("Signature")) == NULL) - 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 || (o = PyString_FromString(lc->lc_type)) == NULL) - goto deldict; - - rc = PyDict_SetItem(ldict,typeName,o); - Py_DECREF(o); - - if (rc < 0) - goto deldict; - - if (lc->lc_licensee != NULL) - { - if ((o = PyString_FromString(lc->lc_licensee)) == NULL) - goto deldict; - - rc = PyDict_SetItem(ldict,licenseeName,o); - Py_DECREF(o); - - if (rc < 0) - goto deldict; - } - - if (lc->lc_timestamp != NULL) - { - if ((o = PyString_FromString(lc->lc_timestamp)) == NULL) - goto deldict; - - rc = PyDict_SetItem(ldict,timestampName,o); - Py_DECREF(o); - - if (rc < 0) - goto deldict; - } - - if (lc->lc_signature != NULL) - { - if ((o = PyString_FromString(lc->lc_signature)) == 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; - - if ((w = PyString_FromStringAndSize(&ci->ci_val,1)) == 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; - - if ((w = PyString_FromString(si->si_val)) == 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 ((w = PyInt_FromLong(ii->ii_val)) == 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 enum instances and add them to a dictionary. - */ -static int addEnumInstances(PyObject *dict, sipEnumInstanceDef *ei) -{ - while (ei->ei_name != NULL) - { - if (addSingleEnumInstance(dict, ei->ei_name, ei->ei_val, *ei->ei_type) < 0) - return -1; - - ++ei; - } - - return 0; -} - - -/* - * Wrap a single enum instance and add it to a dictionary. - */ -static int addSingleEnumInstance(PyObject *dict, const char *name, int value, - PyTypeObject *type) -{ - int rc; - PyObject *w; - - if ((w = sip_api_convert_from_named_enum(value, type)) == NULL) - return -1; - - rc = PyDict_SetItemString(dict, name, w); - Py_DECREF(w); - - return rc; -} - - -/* - * Wrap an enum instance and add it to a dictionary. - */ -static int sip_api_add_enum_instance(PyObject *dict, const char *name, - int value, PyTypeObject *type) -{ - /* If this is a wrapped type then get the type dictionary. */ - if (sipWrapperType_Check(dict)) - dict = ((PyTypeObject *)dict)->tp_dict; - - return addSingleEnumInstance(dict, name, value, type); -} - - -/* - * Wrap a set of class instances and add them to a dictionary. - */ -static int addClassInstances(PyObject *dict, sipClassInstanceDef *ci) -{ - while (ci->ci_name != NULL) - { - if (addSingleClassInstance(dict, ci->ci_name, ci->ci_ptr, *ci->ci_type, ci->ci_flags) < 0) - return -1; - - ++ci; - } - - return 0; -} - - -/* - * Wrap a single class instance and add it to a dictionary. - */ -static int addSingleClassInstance(PyObject *dict, const char *name, - void *cppPtr, sipWrapperType *wt, int initflags) -{ - int rc; - PyObject *w; - - if ((w = sipWrapSimpleInstance(cppPtr,wt,NULL,initflags)) == NULL) - return -1; - - rc = PyDict_SetItemString(dict,name,w); - Py_DECREF(w); - - return rc; -} - - -/* - * Wrap a class instance and add it to a dictionary. - */ -static int sip_api_add_class_instance(PyObject *dict, const char *name, - void *cppPtr, sipWrapperType *wt) -{ - /* If this is a wrapped type then get the type dictionary. */ - if (sipWrapperType_Check(dict)) - dict = ((PyTypeObject *)dict)->tp_dict; - - return addSingleClassInstance(dict, name, cppPtr, wt, 0); -} - - -/* - * Wrap a mapped type instance and add it to a dictionary. - */ -static int sip_api_add_mapped_type_instance(PyObject *dict, const char *name, - void *cppPtr, const sipMappedType *mt) -{ - int rc; - PyObject *w; - - /* If this is a wrapped type then get the type dictionary. */ - if (sipWrapperType_Check(dict)) - dict = ((PyTypeObject *)dict)->tp_dict; - - if ((w = mt->mt_cfrom(cppPtr, NULL)) == NULL) - return -1; - - rc = PyDict_SetItemString(dict, name, w); - Py_DECREF(w); - - return rc; -} - - -/* - * Get the C/C++ pointer for a complex object. - */ -static void *sip_api_get_complex_cpp_ptr(sipWrapper *w) -{ - if (!sipIsDerived(w)) - { - PyErr_SetString(PyExc_RuntimeError,"no access to protected functions or signals for objects not created from Python"); - - return NULL; - } - - if (checkPointer(w->u.cppPtr) < 0) - return NULL; - - return w->u.cppPtr; -} - - -/* - * Return the Python member function 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,sipMethodCache *pymc, - sipWrapper *sipSelf,char *cname, - char *mname) -{ - /* 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 (complex) C/C++ instance is still working and trying to - * handle virtual functions. Or an instance has started handling - * virtual functions before its ctor has returned. In either case say - * there is no Python method. - */ - if (sipSelf == NULL) - return NULL; - -#ifdef WITH_THREAD - *gil = PyGILState_Ensure(); -#endif - - /* See if we have already looked for the Python method. */ - if (!sipFoundMethod(pymc)) - { - PyObject *methobj; - - /* - * Using PyMethod_Check() rather than PyCallable_Check() has - * the added benefits of ensuring the (common) case of there - * being no Python method is handled as a direct call to C/C++ - * (rather than converted to Python and then back to C/C++) and - * makes sure that abstract virtuals are trapped. - */ - if ((methobj = PyObject_GetAttrString((PyObject *)sipSelf,mname)) != NULL) - { - if (PyMethod_Check(methobj)) - { - sipSetIsMethod(pymc); - sipSaveMethod(&pymc->pyMethod,methobj); - } - - Py_DECREF(methobj); - } - - PyErr_Clear(); - - sipSetFoundMethod(pymc); - } - else if (sipIsMethod(pymc)) - PyErr_Clear(); - - if (sipIsMethod(pymc)) - return PyMethod_New(pymc->pyMethod.mfunc,pymc->pyMethod.mself,pymc->pyMethod.mclass); - - if (cname != NULL) - PyErr_Format(PyExc_NotImplementedError,"%s.%s() is abstract and must be overridden",cname,mname); - -#ifdef WITH_THREAD - PyGILState_Release(*gil); -#endif - - return NULL; -} - - -/* - * Convert a C/C++ pointer to the object that wraps it. - */ -static PyObject *sip_api_get_wrapper(void *cppPtr,sipWrapperType *type) -{ - return (PyObject *)sipOMFindObject(&cppPyMap,cppPtr,type); -} - - -/* - * Return the C/C++ pointer from a wrapper without any checks. - */ -void *sipGetAddress(sipWrapper *w) -{ - if (sipIsAccessFunc(w)) - return (*w->u.afPtr)(); - - if (sipIsIndirect(w)) - return *((void **)w->u.cppPtr); - - return w->u.cppPtr; -} - - -/* - * Get the C/C++ pointer from a wrapper and optionally cast it to the required - * type. - */ -void *sip_api_get_cpp_ptr(sipWrapper *w,sipWrapperType *type) -{ - void *ptr = sipGetAddress(w); - - if (checkPointer(ptr) < 0) - return NULL; - - if (type != NULL) - ptr = cast_cpp_ptr(ptr, (sipWrapperType *)w->ob_type, type); - - return ptr; -} - - -/* - * Cast a C/C++ pointer from a source type to a destination type. - */ -static void *cast_cpp_ptr(void *ptr, sipWrapperType *src_type, - sipWrapperType *dst_type) -{ - sipCastFunc cast = src_type->type->td_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; -} - - -/* - * Check to see if a Python object can be converted to a wrapped type. - */ -static int sip_api_can_convert_to_instance(PyObject *pyObj, - sipWrapperType *type, int flags) -{ - int ok; - sipConvertToFunc cto = type->type->td_cto; - - /* None is handled outside the type checkers. */ - if (pyObj == Py_None) - ok = ((flags & SIP_NOT_NONE) == 0); - else if (cto == NULL || (flags & SIP_NO_CONVERTORS) != 0) - ok = PyObject_TypeCheck(pyObj, (PyTypeObject *)type); - else - ok = cto(pyObj, NULL, NULL, NULL); - - return ok; -} - - -/* - * Check to see if a Python object can be converted to a mapped type. - */ -static int sip_api_can_convert_to_mapped_type(PyObject *pyObj, - const sipMappedType *mt, - int flags) -{ - int ok; - - /* None is handled outside the type checkers. */ - if (pyObj == Py_None) - ok = ((flags & SIP_NOT_NONE) == 0); - else - ok = mt->mt_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_instance() has been successful. Allow ownership to - * be transferred and any type convertors to be disabled. - */ -static void *sip_api_convert_to_instance(PyObject *pyObj, sipWrapperType *type, - PyObject *transferObj, int flags, - int *statep, int *iserrp) -{ - void *cpp = NULL; - int state = 0; - sipConvertToFunc cto = type->type->td_cto; - - /* Don't convert if there has already been an error. */ - if (!*iserrp) - { - /* Do the conversion. */ - if (pyObj == Py_None) - cpp = NULL; - else if (cto == NULL || (flags & SIP_NO_CONVERTORS) != 0) - { - if ((cpp = sip_api_get_cpp_ptr((sipWrapper *)pyObj, type)) == 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); - } - - if (statep != NULL) - *statep = state; - - return cpp; -} - - -/* - * Convert a Python object to a C/C++ pointer, assuming a previous call to - * sip_api_can_convert_to_mapped_type() has been successful. Allow ownership - * to be transferred. - */ -static void *sip_api_convert_to_mapped_type(PyObject *pyObj, - const sipMappedType *mt, - PyObject *transferObj, int flags, - int *statep, int *iserrp) -{ - void *cpp = NULL; - int state = 0; - - /* Don't convert if there has already been an error. */ - if (!*iserrp) - if (pyObj == Py_None) - cpp = NULL; - else - state = mt->mt_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_instance(PyObject *pyObj, - sipWrapperType *type, - 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_instance(pyObj, type, flags)) - { - PyErr_Format(PyExc_TypeError, "%s cannot be converted to %s in this context", pyObj->ob_type->tp_name, type->type->td_name); - - if (statep != NULL) - *statep = 0; - - *iserrp = TRUE; - return NULL; - } - - /* Do the conversion. */ - return sip_api_convert_to_instance(pyObj, type, transferObj, flags, statep, iserrp); -} - - -/* - * 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_mapped_type(PyObject *pyObj, - const sipMappedType *mt, - 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_mapped_type(pyObj, mt, flags)) - { - PyErr_Format(PyExc_TypeError, "%s cannot be converted to %s in this context", pyObj->ob_type->tp_name, mt->mt_name); - - if (statep != NULL) - *statep = 0; - - *iserrp = TRUE; - return NULL; - } - - /* Do the conversion. */ - return sip_api_convert_to_mapped_type(pyObj, mt, transferObj, flags, statep, iserrp); -} - - -/* - * Release a possibly temporary instance created by a type convertor. - */ -static void sip_api_release_instance(void *cpp, sipWrapperType *type, int state) -{ - /* See if there is something to release. */ - if (state & SIP_TEMPORARY) - release(cpp, type->type, state); -} - - -/* - * Release an instance. - */ -static void release(void *addr, sipTypeDef *td, int state) -{ - sipReleaseFunc rel = td->td_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 - rel(addr, state); -} - - -/* - * Release a possibly temporary mapped type created by a type convertor. - */ -static void sip_api_release_mapped_type(void *cpp, const sipMappedType *mt, - int state) -{ - /* See if there is something to release. */ - if (state & SIP_TEMPORARY) - { - sipReleaseFunc rel = mt->mt_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(cpp); - else - rel(cpp, state); - } -} - - -/* - * Convert a C/C++ instance to a Python instance. - */ -PyObject *sip_api_convert_from_instance(void *cpp, sipWrapperType *type, - PyObject *transferObj) -{ - PyObject *py; - - /* Handle None. */ - if (cpp == NULL) - { - Py_INCREF(Py_None); - return Py_None; - } - - /* Apply any sub-class convertor. */ - if (sipTypeHasSCC(type)) - type = convertSubClass(type, &cpp); - - /* See if we have already wrapped it. */ - if ((py = sip_api_get_wrapper(cpp, type)) != NULL) - Py_INCREF(py); - else if ((py = sipWrapSimpleInstance(cpp, type, 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_instance(void *cpp, - sipWrapperType *type, - PyObject *transferObj) -{ - sipWrapper *owner; - - /* Handle None. */ - if (cpp == NULL) - { - Py_INCREF(Py_None); - return Py_None; - } - - /* Apply any sub-class convertor. */ - if (sipTypeHasSCC(type)) - type = convertSubClass(type, &cpp); - - /* Handle any ownership transfer. */ - if (transferObj != NULL && transferObj != Py_None) - owner = (sipWrapper *)transferObj; - else - owner = NULL; - - return sipWrapSimpleInstance(cpp, type, owner, (owner == NULL ? SIP_PY_OWNED : 0)); -} - - -/* - * Convert a C/C++ instance implemented as a mapped type to a Python object. - */ -static PyObject *sip_api_convert_from_mapped_type(void *cpp, - const sipMappedType *mt, - PyObject *transferObj) -{ - /* Handle None. */ - if (cpp == NULL) - { - Py_INCREF(Py_None); - return Py_None; - } - - return mt->mt_cfrom(cpp, transferObj); -} - - -/* - * Convert a Python instance of a class to a C/C++ object pointer, checking - * that the instance's class is derived from a given base type. - */ -static void *sip_api_convert_to_cpp(PyObject *sipSelf,sipWrapperType *type, - int *iserrp) -{ - return sip_api_convert_to_instance(sipSelf, type, NULL, SIP_NO_CONVERTORS, NULL, iserrp); -} - - -/* - * 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; -} - - -/* - * Return the mapped type structure for a particular mapped type. - */ -static const sipMappedType *sip_api_find_mapped_type(const char *type) -{ - sipExportedModuleDef *em; - - for (em = clientList; em != NULL; em = em->em_next) - { - sipMappedType **mtypes, *mt; - - if ((mtypes = em->em_mappedtypes) == NULL) - continue; - - while ((mt = *mtypes++) != NULL) - { - const char *s1 = mt->mt_name, *s2 = type; - - /* - * Compare while ignoring spaces so that we don't impose a rigorous - * naming standard. - */ - do - { - while (*s1 == ' ') - ++s1; - - while (*s2 == ' ') - ++s2; - - if (*s1 == '\0' && *s2 == '\0') - return mt; - } - while (*s1++ == *s2++); - } - } - - return NULL; -} - - -/* - * Return the type structure for a particular class. - */ -static sipWrapperType *sip_api_find_class(const char *type) -{ - sipExportedModuleDef *em; - size_t type_len = strlen(type); - - for (em = clientList; em != NULL; em = em->em_next) - { - sipWrapperType *wt = findClass(em, type, type_len); - - if (wt != NULL) - return wt; - } - - return NULL; -} - - -/* - * Return the type structure for a particular named enum. - */ -static PyTypeObject *sip_api_find_named_enum(const char *type) -{ - sipExportedModuleDef *em; - size_t type_len = strlen(type); - - for (em = clientList; em != NULL; em = em->em_next) - { - PyTypeObject *py = findEnum(em, type, type_len); - - if (py != NULL) - return py; - } - - 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); - pm->mclass = PyMethod_GET_CLASS(meth); -} - - -/* - * 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 sipWrapperType *convertSubClass(sipWrapperType *type, void **cppPtr) -{ - 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 = clientList; 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((PyTypeObject *)type, (PyTypeObject *)scc->scc_basetype)) - { - void *ptr; - sipWrapperType *subtype; - - ptr = cast_cpp_ptr(*cppPtr, 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((PyTypeObject *)type, (PyTypeObject *)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 type; -} - - -/* - * 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. - */ -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. - */ -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 - - if (mobj == NULL) - mobj = PyString_FromString("unknown"); - - PyErr_SetObject(PyExc_Exception, mobj); - - SIP_UNBLOCK_THREADS -} - - -/* - * Raise an exception implemented as a class. Make no assumptions about the - * GIL. - */ -static void sip_api_raise_class_exception(sipWrapperType *type,void *ptr) -{ - PyObject *self; - - SIP_BLOCK_THREADS - - self = sipWrapSimpleInstance(ptr,type,NULL,SIP_PY_OWNED); - - PyErr_SetObject((PyObject *)type,self); - - Py_XDECREF(self); - - SIP_UNBLOCK_THREADS -} - - -/* - * Raise an exception implemented as a class or sub-class. Make no assumptions - * about the GIL. - */ -static void sip_api_raise_sub_class_exception(sipWrapperType *type,void *ptr) -{ - PyObject *self; - - SIP_BLOCK_THREADS - - self = sipWrapSimpleInstance(ptr,type,NULL,SIP_PY_OWNED); - - PyErr_SetObject((PyObject *)type,self); - - Py_XDECREF(self); - - SIP_UNBLOCK_THREADS -} - - -/* - * Return the module of an encoded class. - */ -static sipExportedModuleDef *getClassModule(sipEncodedClassDef *enc, - sipExportedModuleDef *em) -{ - if (enc->sc_module != 255) - em = em->em_imports[enc->sc_module].im_module; - - return em; -} - - -/* - * Return the type of an encoded class. - */ -static sipWrapperType *getClassType(sipEncodedClassDef *enc, - sipExportedModuleDef *em) -{ - return getClassModule(enc, em)->em_types[enc->sc_class]; -} - - -/* - * Find a particular slot function for a wrapper. - */ -static void *findSlot(PyObject *self,sipPySlotType st) -{ - sipTypeDef *td = ((sipWrapperType *)(self->ob_type))->type; - sipEncodedClassDef *sup; - void *slot; - - /* Check the immediate type. */ - if ((slot = findSlotInType(td, st)) != NULL) - return slot; - - /* Check the super-types, if there are any. */ - if ((sup = td->td_supers) != NULL) - do - if ((slot = findSlotInType(getClassType(sup, td->td_module)->type, st)) != NULL) - return slot; - while (!sup++->sc_flag); - - /* This should never happen. */ - return NULL; -} - - -/* - * Find a particular slot function in a type. - */ -static void *findSlotInType(sipTypeDef *td, sipPySlotType st) -{ - sipPySlotDef *psd; - - if ((psd = td->td_pyslots) != NULL) - while (psd->psd_func != NULL) - { - if (psd->psd_type == st) - return psd->psd_func; - - ++psd; - } - - return NULL; -} - - -/* - * Return the C/C++ address and the basic type information for a wrapper. - */ -static void *getPtrTypeDef(sipWrapper *self, sipTypeDef **td) -{ - *td = ((sipWrapperType *)self->ob_type)->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 *); - PyObject *args; - int res; - - /* - * Slot handlers require a single PyObject *. The second argument is - * optional. - */ - if (arg2 == NULL) - args = arg1; - else if (PyTuple_Check(arg1)) - { - int i; - - /* - * It's already a tuple so we need to copy it and append the - * value. - */ - if ((args = PyTuple_New(PyTuple_GET_SIZE(arg1) + 1)) == NULL) - return -1; - - for (i = 0; i < PyTuple_GET_SIZE(arg1); ++i) - { - PyObject *o = PyTuple_GET_ITEM(arg1,i); - - PyTuple_SET_ITEM(args,i,o); - Py_INCREF(o); - } - - PyTuple_SET_ITEM(args,i,arg2); - Py_INCREF(arg2); - } - else if ((args = Py_BuildValue("(OO)",arg1,arg2)) == NULL) - return -1; - - f = (int (*)(PyObject *,PyObject *))findSlot(self,st); - - res = f(self,args); - - if (arg2 != NULL) - { - Py_DECREF(args); - } - - return res; -} - - -/* - * Handle an ssizeobjargproc slot. - */ -static int ssizeobjargprocSlot(PyObject *self, SIP_SSIZE_T arg1, - PyObject *arg2, sipPySlotType st) -{ - int (*f)(PyObject *,PyObject *); - PyObject *args; - int res; - - /* - * Slot handlers require a single PyObject *. The second argument is - * optional. - */ - if (arg2 == NULL) -#if 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; - - f = (int (*)(PyObject *,PyObject *))findSlot(self,st); - - res = f(self,args); - - Py_DECREF(args); - - return res; -} - - -/***************************************************************************** - * The functions, data types and structures to support a Python type to hold a - * void * that can be converted to an integer. - *****************************************************************************/ - -/* The object data structure. */ -typedef struct { - PyObject_HEAD - void *voidptr; -} sipVoidPtr; - - -/* - * Implement __new__ for the type. - */ -static PyObject *sipVoidPtr_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds) -{ - PyObject *obj; - void *ptr; - int nargs, bad; - - /* We don't support keyword arguments. */ - if (kwds != NULL) - { - PyErr_SetString(PyExc_TypeError, "keyword arguments are not supported"); - return NULL; - } - - /* Get the single argument. */ - if ((nargs = PyTuple_Size(args)) < 0) - return NULL; - - bad = FALSE; - - if (nargs == 1) - { - PyObject *arg = PyTuple_GET_ITEM(args, 0); - - if (arg == Py_None) - ptr = NULL; - else if (PyCObject_Check(arg)) - ptr = PyCObject_AsVoidPtr(arg); - else if (arg->ob_type == &sipVoidPtr_Type) - { - /* - * The type is immutable so just return the argument. - */ - Py_INCREF(arg); - return arg; - } - else - { - ptr = (void *)PyInt_AsLong(arg); - - if (PyErr_Occurred()) - bad = TRUE; - } - } - else - bad = TRUE; - - if (bad) - { - PyErr_SetString(PyExc_TypeError, "a single integer, CObject, None or another voidptr is required"); - return NULL; - } - - /* Create the instance. */ - if ((obj = subtype->tp_alloc(subtype, 0)) == NULL) - return NULL; - - /* Save the pointer. */ - ((sipVoidPtr *)obj)->voidptr = ptr; - - return obj; -} - - -/* - * Implement int() for the type. - */ -static PyObject *sipVoidPtr_int(sipVoidPtr *v) -{ - return PyInt_FromLong((long)v->voidptr); -} - - -/* - * Implement hex() for the type. - */ -static PyObject *sipVoidPtr_hex(sipVoidPtr *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); -} - - -/* - * Implement ascobject() for the type. - */ -static PyObject *sipVoidPtr_ascobject(sipVoidPtr *v, PyObject *arg) -{ - return PyCObject_FromVoidPtr(v->voidptr, NULL); -} - - -/* - * Implement asstring() for the type. - */ -static PyObject *sipVoidPtr_asstring(sipVoidPtr *v,PyObject *arg) -{ - long nbytes = PyInt_AsLong(arg); - - if (PyErr_Occurred()) - return NULL; - - return PyString_FromStringAndSize(v->voidptr,nbytes); -} - - -/* The methods data structure. */ -static PyMethodDef sipVoidPtr_Methods[] = { - {"ascobject", (PyCFunction)sipVoidPtr_ascobject, METH_NOARGS, NULL}, - {"asstring", (PyCFunction)sipVoidPtr_asstring, METH_O, NULL}, - {NULL} -}; - - -/* The number methods data structure. */ -PyNumberMethods sipVoidPtr_NumberMethods = { - 0, /* nb_add */ - 0, /* nb_subtract */ - 0, /* nb_multiply */ - 0, /* nb_divide */ - 0, /* nb_remainder */ - 0, /* nb_divmod */ - 0, /* nb_power */ - 0, /* nb_negative */ - 0, /* nb_positive */ - 0, /* nb_absolute */ - 0, /* nb_nonzero */ - 0, /* nb_invert */ - 0, /* nb_lshift */ - 0, /* nb_rshift */ - 0, /* nb_and */ - 0, /* nb_xor */ - 0, /* nb_or */ - 0, /* nb_coerce */ - (unaryfunc)sipVoidPtr_int, /* nb_int */ - 0, /* nb_long */ - 0, /* nb_float */ - 0, /* nb_oct */ - (unaryfunc)sipVoidPtr_hex, /* nb_hex */ -}; - - -/* The type data structure. */ -static PyTypeObject sipVoidPtr_Type = { - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ - "sip.voidptr", /* tp_name */ - sizeof (sipVoidPtr), /* tp_basicsize */ - 0, /* tp_itemsize */ - 0, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - 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 */ - 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 */ - 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. - */ -static 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; - - /* Save a conversion if it's not a sub-type. */ - if (obj->ob_type == &sipVoidPtr_Type) - return ((sipVoidPtr *)obj)->voidptr; - - return (void *)PyInt_AsLong(obj); -} - - -/* - * A convenience function to convert a C/C++ void pointer to a Python object. - */ -PyObject *sip_api_convert_from_void_ptr(void *val) -{ - sipVoidPtr *self; - - if (val == NULL) - { - Py_INCREF(Py_None); - return Py_None; - } - - if ((self = PyObject_NEW(sipVoidPtr,&sipVoidPtr_Type)) == NULL) - return NULL; - - self->voidptr = val; - - return (PyObject *)self; -} - - -/* - * Return TRUE if a type is a wrapped type, rather than a sub-type implemented - * in Python or the super-type. - */ -static int isExactWrappedType(sipWrapperType *wt) -{ - char *name; - - /* - * We check by comparing the actual type name with the name used to create - * the original wrapped type. - */ -#if PY_VERSION_HEX >= 0x02050000 - if ((name = PyString_AsString(wt->super.ht_name)) == NULL) -#else - if ((name = PyString_AsString(wt->super.name)) == NULL) -#endif - return FALSE; - - return (strcmp(name, getBaseName(wt->type->td_name)) == 0); -} - - -/***************************************************************************** - * The Python metatype for a C++ wrapper type. - *****************************************************************************/ - -/* - * The type 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; - addSlots((sipWrapperType *)o, currentType); - currentType = NULL; - } - - return o; -} - - -/* - * The type 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 *sc = ((PyTypeObject *)self)->tp_base; - - /* - * Make sure that the type is derived from sip.wrapper. It might not - * if the type specifies sip.wrappertype as the __metaclass__. - */ - if (sc == NULL || !sipWrapperType_Check((PyObject *)sc)) - { - PyErr_Format(PyExc_TypeError, - "type %s must be derived from sip.wrapper", - ((PyTypeObject *)self)->tp_name); - - return -1; - } - - self->type = ((sipWrapperType *)sc)->type; - } - - return 0; -} - - -/* - * The type getattro slot. - */ -static PyObject *sipWrapperType_getattro(PyObject *obj,PyObject *name) -{ - char *nm; - PyObject *attr; - sipWrapperType *wt = (sipWrapperType *)obj; - - /* - * If we are getting the type dictionary for a base wrapped type then we - * don't want the super-metatype to handle it. - */ - if ((nm = PyString_AsString(name)) == NULL) - return NULL; - - if (strcmp(nm, "__dict__") == 0) - { - int i; - sipTypeDef *td; - sipEnumMemberDef *enm; - PyObject *dict; - PyMethodDef *pmd; - - dict = ((PyTypeObject *)wt)->tp_dict; - - /* The base type doesn't have any type information. */ - if ((td = wt->type) == NULL || !isExactWrappedType(wt)) - { - Py_INCREF(dict); - return dict; - } - - /* - * We can't cache the methods or variables so we need to make a - * temporary copy of the type dictionary and return that (so - * that it will get garbage collected immediately afterwards). - */ - if ((dict = PyDict_Copy(dict)) == NULL) - return NULL; - - /* Search the possible linked list of namespace extenders. */ - do - { - /* - * Add the type's lazy enums. It doesn't matter if - * they are already there. - */ - enm = td->td_enummembers; - - for (i = 0; i < td->td_nrenummembers; ++i) - { - int rc; - PyObject *val; - - if ((val = createEnumMember(td, enm)) == NULL) - return NULL; - - rc = PyDict_SetItemString(dict, enm->em_name, val); - - Py_DECREF(val); - - if (rc < 0) - return NULL; - - ++enm; - } - - /* Do the methods. */ - pmd = td->td_methods; - - for (i = 0; i < td->td_nrmethods; ++i) - { - int rc; - PyObject *meth; - - if ((meth = PyCFunction_New(pmd, NULL)) == NULL) - { - Py_DECREF(dict); - return NULL; - } - - rc = PyDict_SetItemString(dict, pmd->ml_name, meth); - - Py_DECREF(meth); - - if (rc < 0) - { - Py_DECREF(dict); - return NULL; - } - - ++pmd; - } - - /* Do the static variables. */ - if ((pmd = td->td_variables) != NULL) - while (pmd->ml_name != NULL) - { - if ((pmd->ml_flags & METH_STATIC) != 0) - { - int rc; - PyObject *val; - - if ((val = (*pmd->ml_meth)(NULL, NULL)) == NULL) - { - Py_DECREF(dict); - return NULL; - } - - rc = PyDict_SetItemString(dict, pmd->ml_name, val); - - Py_DECREF(val); - - if (rc < 0) - { - Py_DECREF(dict); - return NULL; - } - } - - ++pmd; - } - - td = td->td_nsextender; - } - while (td != NULL); - - return dict; - } - - /* Now try the super-metatype's method. */ - if ((attr = PyType_Type.tp_getattro(obj,name)) != NULL) - return attr; - - return handleGetLazyAttr(name,wt,NULL); -} - - -/* - * The type setattro slot. - */ -static int sipWrapperType_setattro(PyObject *obj,PyObject *name,PyObject *value) -{ - int rc; - - rc = handleSetLazyAttr(name,value,(sipWrapperType *)obj,NULL); - - if (rc <= 0) - return rc; - - /* Try the super-type's method last. */ - return PyType_Type.tp_setattro(obj,name,value); -} - - -/* - * The type data structure. 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 PyTypeObject sipWrapperType_Type = { - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ - "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_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 */ - 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. - *****************************************************************************/ - -/* - * The instance new slot. - */ -static PyObject *sipWrapper_new(sipWrapperType *wt,PyObject *args,PyObject *kwds) -{ - /* See if it is a namespace. */ - if (wt->type->td_fcto == NULL) - { - PyErr_Format(PyExc_TypeError, "%s represents a C++ namespace that cannot be instantiated", wt->type->td_name); - - 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 (wt->type->td_init == NULL) - { - PyErr_Format(PyExc_TypeError,"%s cannot be instantiated or sub-classed", wt->type->td_name); - - return NULL; - } - - /* See if it is an abstract type. */ - if (sipTypeIsAbstract(wt) && strcmp(strchr(wt->type->td_name, '.') + 1, ((PyTypeObject *)wt)->tp_name) == 0) - { - PyErr_Format(PyExc_TypeError, "%s represents a C++ abstract class and cannot be instantiated", wt->type->td_name); - - return NULL; - } - } - - /* Call the standard super-type new. */ - return PyBaseObject_Type.tp_new((PyTypeObject *)wt, args, kwds); -} - - -/* - * The instance init slot. - */ -static int sipWrapper_init(sipWrapper *self,PyObject *args,PyObject *kwds) -{ - void *sipNew; - int sipFlags; - sipWrapper *owner; - - if (self->ob_type == (PyTypeObject *)&sipWrapper_Type) - { - PyErr_SetString(PyExc_TypeError,"the sip.wrapper type cannot be instantiated"); - return -1; - } - - if (kwds != NULL) - { - PyErr_SetString(PyExc_TypeError,"keyword arguments are not supported"); - return -1; - } - - /* Check there is no existing C++ instance waiting to be wrapped. */ - if ((sipNew = sipGetPending(&owner, &sipFlags)) == NULL) - { - int argsparsed = 0; - sipWrapperType *wt = (sipWrapperType *)self->ob_type; - - /* Call the C++ ctor. */ - owner = NULL; - - if ((sipNew = wt->type->td_init(self, args, &owner, &argsparsed)) != NULL) - sipFlags = SIP_DERIVED_CLASS; - else - { - int pstate = argsparsed & PARSE_MASK; - sipInitExtenderDef *ie = wt->iextend; - - /* - * While we just have signature errors, try any initialiser - * extenders. - */ - while (ie != NULL && (pstate == PARSE_MANY || pstate == PARSE_FEW || pstate == PARSE_TYPE)) - { - argsparsed = 0; - - if ((sipNew = ie->ie_extender(self, args, &owner, &argsparsed)) != NULL) - break; - - pstate = argsparsed & PARSE_MASK; - ie = ie->ie_next; - } - - if (sipNew == NULL) - { - /* - * If the arguments were parsed without error then assume an - * exception has already been raised for why the instance - * wasn't created. - */ - if (pstate == PARSE_OK) - argsparsed = PARSE_RAISED; - - badArgs(argsparsed, NULL, getBaseName(wt->type->td_name)); - return -1; - } - - sipFlags = 0; - } - - if (owner == NULL) - sipFlags |= SIP_PY_OWNED; - } - - addToParent(self, owner); - - self->u.cppPtr = sipNew; - self->flags = sipFlags; - - if (!sipNotInMap(self)) - sipOMAddObject(&cppPyMap,self); - - return 0; -} - - -/* - * The instance traverse slot. - */ -static int sipWrapper_traverse(sipWrapper *self, visitproc visit, void *arg) -{ - int vret; - void *ptr; - sipTypeDef *td; - sipWrapper *w; - sipPySig *ps; - - /* Call the nearest handwritten traverse code in the class hierachy. */ - if ((ptr = getPtrTypeDef(self, &td)) != NULL) - { - sipTypeDef *ctd = td; - - if (td->td_traverse == NULL) - { - sipEncodedClassDef *sup; - - if ((sup = td->td_supers) != NULL) - do - ctd = getClassType(sup, td->td_module)->type; - while (ctd->td_traverse == NULL && !sup++->sc_flag); - } - - if (ctd->td_traverse != NULL) - if ((vret = ctd->td_traverse(ptr, visit, arg)) != 0) - return vret; - } - - if (qt_and_sip_api_3_4()) - { - void *tx = sipGetAddress(self); - - if (tx != NULL) - { - sipSlotConnection *conn; - void *context = NULL; - - while ((conn = sipQtSupport->qt_find_connection(tx, &context)) != NULL) - { - if ((vret = visitSlot(&conn->sc_slot, visit, arg)) != 0) - return vret; - - if (context == NULL) - break; - } - } - } - - for (ps = self->pySigList; ps != NULL; ps = ps->next) - { - sipSlotList *psrx; - - for (psrx = ps->rxlist; psrx != NULL; psrx = psrx->next) - if ((vret = visitSlot(&psrx->rx, visit, arg)) != 0) - return vret; - } - - if (self->user != NULL) - if ((vret = visit(self->user, arg)) != 0) - return vret; - - if (self->dict != NULL) - if ((vret = visit(self->dict, arg)) != 0) - return vret; - - 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; -} - - -/* - * The instance clear slot. - */ -static int sipWrapper_clear(sipWrapper *self) -{ - int vret = 0; - void *ptr; - sipTypeDef *td; - PyObject *tmp; - sipPySig *ps; - - /* Call the nearest handwritten clear code in the class hierachy. */ - if ((ptr = getPtrTypeDef(self, &td)) != NULL) - { - sipTypeDef *ctd = td; - - if (td->td_clear == NULL) - { - sipEncodedClassDef *sup; - - if ((sup = td->td_supers) != NULL) - do - ctd = getClassType(sup, td->td_module)->type; - while (ctd->td_clear == NULL && !sup++->sc_flag); - } - - if (ctd->td_clear != NULL) - vret = ctd->td_clear(ptr); - } - - /* Remove any lambda slots connected via a proxy. */ - if (qt_and_sip_api_3_4()) - { - void *tx = sipGetAddress(self); - - if (tx != NULL) - { - sipSlotConnection *conn; - void *context = NULL; - - while ((conn = sipQtSupport->qt_find_connection(tx, &context)) != NULL) - { - clearAnyLambda(&conn->sc_slot); - - if (context == NULL) - break; - } - } - } - - /* Remove any lambda slots connected to PyQt v3 Python signals. */ - for (ps = self->pySigList; ps != NULL; ps = ps->next) - { - sipSlotList *psrx; - - for (psrx = ps->rxlist; psrx != NULL; psrx = psrx->next) - clearAnyLambda(&psrx->rx); - } - - /* Remove any user object. */ - tmp = self->user; - self->user = NULL; - Py_XDECREF(tmp); - - /* Remove the instance dictionary. */ - tmp = self->dict; - self->dict = NULL; - Py_XDECREF(tmp); - - /* Detach children (which will be owned by C/C++. */ - while (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(self->first_child); - sipSetCppHasRef(self->first_child); - - removeFromParent(self->first_child); - } - - return vret; -} - - -/* - * The instance read buffer slot. - */ -static SIP_SSIZE_T sipWrapper_getreadbuffer(sipWrapper *self, - SIP_SSIZE_T segment, void **ptrptr) -{ - void *ptr; - sipTypeDef *td; - - if ((ptr = getPtrTypeDef(self, &td)) == NULL) - return -1; - - return td->td_readbuffer((PyObject *)self, ptr, segment, ptrptr); -} - - -/* - * The instance write buffer slot. - */ -static SIP_SSIZE_T sipWrapper_getwritebuffer(sipWrapper *self, - SIP_SSIZE_T segment, void **ptrptr) -{ - void *ptr; - sipTypeDef *td; - - if ((ptr = getPtrTypeDef(self, &td)) == NULL) - return -1; - - return td->td_writebuffer((PyObject *)self, ptr, segment, ptrptr); -} - - -/* - * The instance segment count slot. - */ -static SIP_SSIZE_T sipWrapper_getsegcount(sipWrapper *self, SIP_SSIZE_T *lenp) -{ - void *ptr; - sipTypeDef *td; - - if ((ptr = getPtrTypeDef(self, &td)) == NULL) - return 0; - - return td->td_segcount((PyObject *)self, ptr, lenp); -} - - -/* - * The instance char buffer slot. - */ -static SIP_SSIZE_T sipWrapper_getcharbuffer(sipWrapper *self, - SIP_SSIZE_T segment, void **ptrptr) -{ - void *ptr; - sipTypeDef *td; - - if ((ptr = getPtrTypeDef(self, &td)) == NULL) - return -1; - - return td->td_charbuffer((PyObject *)self, ptr, segment, ptrptr); -} - - -/* - * The instance dealloc slot. - */ -static void sipWrapper_dealloc(sipWrapper *self) -{ - sipTypeDef *td; - - if (getPtrTypeDef(self, &td) != 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, self); - - /* Call the C++ dtor if there is one. */ - if (td->td_dealloc != NULL) - td->td_dealloc(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 TQObject.destroyed()). - */ - sipWrapper_clear(self); - - while (self->pySigList != NULL) - { - sipPySig *ps; - sipSlotList *psrx; - - /* Take this one out of the list. */ - ps = self->pySigList; - self->pySigList = ps->next; - - while ((psrx = ps->rxlist) != NULL) - { - ps->rxlist = psrx->next; - sipFreeSlotList(psrx); - } - - sip_api_free(ps->name); - sip_api_free(ps); - } - - /* Call the standard super-type dealloc. */ - PyBaseObject_Type.tp_dealloc((PyObject *)self); -} - - -/* - * The instance call slot. Note that keyword arguments aren't supported. - */ -static PyObject *sipWrapper_call(PyObject *self,PyObject *args,PyObject *kw) -{ - PyObject *(*f)(PyObject *,PyObject *); - - f = (PyObject *(*)(PyObject *,PyObject *))findSlot(self,call_slot); - - return f(self,args); -} - - -/* - * The sequence instance item slot. - */ -static PyObject *sipWrapper_sq_item(PyObject *self, SIP_SSIZE_T n) -{ - PyObject *(*f)(PyObject *,PyObject *); - PyObject *arg, *res; - -#if PY_VERSION_HEX >= 0x02050000 - if ((arg = PyInt_FromSsize_t(n)) == NULL) -#else - if ((arg = PyInt_FromLong(n)) == NULL) -#endif - return NULL; - - f = (PyObject *(*)(PyObject *,PyObject *))findSlot(self,getitem_slot); - - res = f(self,arg); - - Py_DECREF(arg); - - return res; -} - - -/* - * The mapping instance assign subscript slot. - */ -static int sipWrapper_mp_ass_subscript(PyObject *self,PyObject *key, - PyObject *value) -{ - return objobjargprocSlot(self,key,value,(value != NULL ? setitem_slot : delitem_slot)); -} - - -/* - * The sequence instance assign item slot. - */ -static int sipWrapper_sq_ass_item(PyObject *self, SIP_SSIZE_T i, PyObject *o) -{ - return ssizeobjargprocSlot(self, i, o, (o != NULL ? setitem_slot : delitem_slot)); -} - - -/* - * The instance rich compare slot. - */ -static PyObject *sipWrapper_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 *sipWrapper_getattro(PyObject *obj,PyObject *name) -{ - char *nm; - PyObject *attr; - sipWrapperType *wt = (sipWrapperType *)obj->ob_type; - sipWrapper *w = (sipWrapper *)obj; - - /* - * If we are getting the instance dictionary of a base wrapper type - * then we don't want the metatype to handle it. - */ - if ((nm = PyString_AsString(name)) == NULL) - return NULL; - - if (strcmp(nm, "__dict__") == 0) - { - PyObject *tmpdict = NULL; - - if (isExactWrappedType(wt) && getNonStaticVariables(wt, w, &tmpdict) < 0) - { - Py_XDECREF(tmpdict); - return NULL; - } - - /* - * If a copy of the instance dictionary wasn't created then - * just return the original. Note that Python doesn't want a - * proxy. - */ - if (tmpdict == NULL) - if ((tmpdict = w->dict) == NULL) - tmpdict = PyDict_New(); - else - Py_INCREF(tmpdict); - - return tmpdict; - } - - /* Try the super-type's method first. */ - if ((attr = PyBaseObject_Type.tp_getattro(obj,name)) != NULL) - return attr; - - return handleGetLazyAttr(name,wt,w); -} - - -/* - * Add the values of all non-static variables to a dictionary (first making a - * copy of the dictionary if needed). - */ -static int getNonStaticVariables(sipWrapperType *wt,sipWrapper *w, - PyObject **ndict) -{ - PyMethodDef *pmd; - - if ((pmd = wt->type->td_variables) != NULL) - while (pmd->ml_name != NULL) - { - if ((pmd->ml_flags & METH_STATIC) == 0) - { - int rc; - PyObject *val, *dict; - - /* - * Create a copy of the original dictionary if - * it hasn't already been done. - */ - if ((dict = *ndict) == NULL) - { - if ((dict = PyDict_Copy(w->dict)) == NULL) - return -1; - - *ndict = dict; - } - - if ((val = (*pmd->ml_meth)((PyObject *)w,NULL)) == NULL) - return -1; - - rc = PyDict_SetItemString(dict,pmd->ml_name,val); - - Py_DECREF(val); - - if (rc < 0) - return -1; - } - - ++pmd; - } - - return 0; -} - - -/* - * The instance setattro slot. - */ -static int sipWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value) -{ - int rc; - - rc = handleSetLazyAttr(name,value,(sipWrapperType *)obj->ob_type,(sipWrapper *)obj); - - if (rc <= 0) - return rc; - - /* Try the super-type's method last. */ - return PyBaseObject_Type.tp_setattro(obj,name,value); -} - - -/* - * 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. - */ -static sipWrapperType sipWrapper_Type = { - { - { - PyObject_HEAD_INIT(&sipWrapperType_Type) - 0, /* ob_size */ - "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_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 */ - sipWrapper_getattro, /* tp_getattro */ - sipWrapper_setattro, /* 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 */ - offsetof(sipWrapper,dict), /* tp_dictoffset */ - (initproc)sipWrapper_init, /* tp_init */ - 0, /* tp_alloc */ - (newfunc)sipWrapper_new, /* tp_new */ - 0, /* tp_free */ - }, - }, - 0, - 0 -}; - - -/* - * Add the slots for a type and all its super-types. - */ -static void addSlots(sipWrapperType *wt, sipTypeDef *td) -{ - sipEncodedClassDef *sup; - - /* Add the buffer interface. */ - if (td->td_readbuffer != NULL) -#if PY_VERSION_HEX >= 0x02050000 - wt->super.as_buffer.bf_getreadbuffer = (readbufferproc)sipWrapper_getreadbuffer; -#else - wt->super.as_buffer.bf_getreadbuffer = (getreadbufferproc)sipWrapper_getreadbuffer; -#endif - - if (td->td_writebuffer != NULL) -#if PY_VERSION_HEX >= 0x02050000 - wt->super.as_buffer.bf_getwritebuffer = (writebufferproc)sipWrapper_getwritebuffer; -#else - wt->super.as_buffer.bf_getwritebuffer = (getwritebufferproc)sipWrapper_getwritebuffer; -#endif - - if (td->td_segcount != NULL) -#if PY_VERSION_HEX >= 0x02050000 - wt->super.as_buffer.bf_getsegcount = (segcountproc)sipWrapper_getsegcount; -#else - wt->super.as_buffer.bf_getsegcount = (getsegcountproc)sipWrapper_getsegcount; -#endif - - if (td->td_charbuffer != NULL) -#if PY_VERSION_HEX >= 0x02050000 - wt->super.as_buffer.bf_getcharbuffer = (charbufferproc)sipWrapper_getcharbuffer; -#else - wt->super.as_buffer.bf_getcharbuffer = (getcharbufferproc)sipWrapper_getcharbuffer; -#endif - - /* Add the slots for this type. */ - if (td->td_pyslots != NULL) - initSlots((PyTypeObject *)wt, &wt->super.as_number, &wt->super.as_sequence, &wt->super.as_mapping, td->td_pyslots, FALSE); - - /* Recurse through any super-types. */ - if ((sup = td->td_supers) != NULL) - do - addSlots(wt, getClassType(sup, td->td_module)->type); - while (!sup++->sc_flag); -} - - -/* - * Add the slot handler for each slot present in the type, optionally replacing - * any that have already been defined. - */ -static void initSlots(PyTypeObject *to, PyNumberMethods *nb, PySequenceMethods *sq, PyMappingMethods *mp, sipPySlotDef *slots, int force) -{ - void *f; - - while ((f = slots->psd_func) != NULL) - switch (slots++->psd_type) - { - case str_slot: - if (force || to->tp_str == NULL) - to->tp_str = (reprfunc)f; - break; - - case int_slot: - if (nb != NULL) - if (force || nb->nb_int == NULL) - nb->nb_int = (unaryfunc)f; - break; - - case long_slot: - if (nb != NULL) - if (force || nb->nb_long == NULL) - nb->nb_long = (unaryfunc)f; - break; - - case float_slot: - if (nb != NULL) - if (force || nb->nb_float == NULL) - nb->nb_float = (unaryfunc)f; - break; - - case len_slot: - if (mp != NULL) - if (force || mp->mp_length == NULL) -#if PY_VERSION_HEX >= 0x02050000 - mp->mp_length = (lenfunc)f; -#else - mp->mp_length = (inquiry)f; -#endif - if (sq != NULL) - if (force || sq->sq_length == 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) - if (force || sq->sq_contains == NULL) - sq->sq_contains = (objobjproc)f; - break; - - case add_slot: - if (nb != NULL) - if (force || nb->nb_add == NULL) - nb->nb_add = (binaryfunc)f; - break; - - case concat_slot: - if (sq != NULL) - if (force || sq->sq_concat == NULL) - sq->sq_concat = (binaryfunc)f; - break; - - case sub_slot: - if (nb != NULL) - if (force || nb->nb_subtract == NULL) - nb->nb_subtract = (binaryfunc)f; - break; - - case mul_slot: - if (nb != NULL) - if (force || nb->nb_multiply == NULL) - nb->nb_multiply = (binaryfunc)f; - break; - - case repeat_slot: - if (sq != NULL) - if (force || sq->sq_repeat == 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) - { - if (force || nb->nb_divide == NULL) - nb->nb_divide = (binaryfunc)f; - - if (force || nb->nb_true_divide == NULL) - nb->nb_true_divide = (binaryfunc)f; - } - break; - - case mod_slot: - if (nb != NULL) - if (force || nb->nb_remainder == NULL) - nb->nb_remainder = (binaryfunc)f; - break; - - case and_slot: - if (nb != NULL) - if (force || nb->nb_and == NULL) - nb->nb_and = (binaryfunc)f; - break; - - case or_slot: - if (nb != NULL) - if (force || nb->nb_or == NULL) - nb->nb_or = (binaryfunc)f; - break; - - case xor_slot: - if (nb != NULL) - if (force || nb->nb_xor == NULL) - nb->nb_xor = (binaryfunc)f; - break; - - case lshift_slot: - if (nb != NULL) - if (force || nb->nb_lshift == NULL) - nb->nb_lshift = (binaryfunc)f; - break; - - case rshift_slot: - if (nb != NULL) - if (force || nb->nb_rshift == NULL) - nb->nb_rshift = (binaryfunc)f; - break; - - case iadd_slot: - if (nb != NULL) - if (force || nb->nb_inplace_add == NULL) - nb->nb_inplace_add = (binaryfunc)f; - break; - - case iconcat_slot: - if (sq != NULL) - if (force || sq->sq_inplace_concat == NULL) - sq->sq_inplace_concat = (binaryfunc)f; - break; - - case isub_slot: - if (nb != NULL) - if (force || nb->nb_inplace_subtract == NULL) - nb->nb_inplace_subtract = (binaryfunc)f; - break; - - case imul_slot: - if (nb != NULL) - if (force || nb->nb_inplace_multiply == NULL) - nb->nb_inplace_multiply = (binaryfunc)f; - break; - - case irepeat_slot: - if (sq != NULL) - if (force || sq->sq_inplace_repeat == 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) - { - if (force || nb->nb_inplace_divide == NULL) - nb->nb_inplace_divide = (binaryfunc)f; - - if (force || nb->nb_inplace_true_divide == NULL) - nb->nb_inplace_true_divide = (binaryfunc)f; - } - break; - - case imod_slot: - if (nb != NULL) - if (force || nb->nb_inplace_remainder == NULL) - nb->nb_inplace_remainder = (binaryfunc)f; - break; - - case iand_slot: - if (nb != NULL) - if (force || nb->nb_inplace_and == NULL) - nb->nb_inplace_and = (binaryfunc)f; - break; - - case ior_slot: - if (nb != NULL) - if (force || nb->nb_inplace_or == NULL) - nb->nb_inplace_or = (binaryfunc)f; - break; - - case ixor_slot: - if (nb != NULL) - if (force || nb->nb_inplace_xor == NULL) - nb->nb_inplace_xor = (binaryfunc)f; - break; - - case ilshift_slot: - if (nb != NULL) - if (force || nb->nb_inplace_lshift == NULL) - nb->nb_inplace_lshift = (binaryfunc)f; - break; - - case irshift_slot: - if (nb != NULL) - if (force || nb->nb_inplace_rshift == NULL) - nb->nb_inplace_rshift = (binaryfunc)f; - break; - - case invert_slot: - if (nb != NULL) - if (force || nb->nb_invert == NULL) - nb->nb_invert = (unaryfunc)f; - break; - - case call_slot: - if (force || to->tp_call == NULL) - to->tp_call = sipWrapper_call; - break; - - case getitem_slot: - if (mp != NULL) - if (force || mp->mp_subscript == NULL) - mp->mp_subscript = (binaryfunc)f; - if (sq != NULL) - if (force || sq->sq_item == NULL) - sq->sq_item = sipWrapper_sq_item; - break; - - case setitem_slot: - case delitem_slot: - if (mp != NULL) - if (force || mp->mp_ass_subscript == NULL) - mp->mp_ass_subscript = sipWrapper_mp_ass_subscript; - if (sq != NULL) - if (force || sq->sq_ass_item == NULL) - sq->sq_ass_item = sipWrapper_sq_ass_item; - break; - - case lt_slot: - case le_slot: - case eq_slot: - case ne_slot: - case gt_slot: - case ge_slot: - if (force || to->tp_richcompare == NULL) - to->tp_richcompare = sipWrapper_richcompare; - break; - - case cmp_slot: - if (force || to->tp_compare == NULL) - to->tp_compare = (cmpfunc)f; - break; - - case nonzero_slot: - if (nb != NULL) - if (force || nb->nb_nonzero == NULL) - nb->nb_nonzero = (inquiry)f; - break; - - case neg_slot: - if (nb != NULL) - if (force || nb->nb_negative == NULL) - nb->nb_negative = (unaryfunc)f; - break; - - case repr_slot: - if (force || to->tp_repr == NULL) - to->tp_repr = (reprfunc)f; - break; - - case hash_slot: - if (force || to->tp_hash == NULL) - to->tp_hash = (hashfunc)f; - break; - - case pos_slot: - if (nb != NULL) - if (force || nb->nb_positive == NULL) - nb->nb_positive = (unaryfunc)f; - break; - - case abs_slot: - if (nb != NULL) - if (force || nb->nb_absolute == NULL) - nb->nb_absolute = (unaryfunc)f; - break; - } -} - - -/* - * Search for a named class and return the wrapper type. - */ -static sipWrapperType *findClass(sipExportedModuleDef *emd, const char *name, - size_t len) -{ - int i; - sipWrapperType **wtp = emd->em_types; - - for (i = 0; i < emd->em_nrtypes; ++i) - { - sipWrapperType *wt; - - if ((wt = *wtp++) == NULL) - continue; - - if (wt->type->td_cname != NULL) - { - if (!nameEq(wt->type->td_cname, name, len)) - continue; - } - else if (!sameScopedName(wt->type->td_name, name, len)) - continue; - - return wt; - } - - return NULL; -} - - -/* - * Search for a named class and return TRUE and the necessary information to - * create an instance of it if it was found. - */ -static int findClassArg(sipExportedModuleDef *emd, const char *name, - size_t len, sipSigArg *at, int indir) -{ - sipWrapperType *wt = findClass(emd, name, len); - - if (wt == NULL) - return FALSE; - - if (indir == 0) - at->atype = class_sat; - else if (indir == 1) - at->atype = classp_sat; - else - at->atype = unknown_sat; - - at->u.wt = wt; - - return TRUE; -} - - -/* - * Search for a mapped type and return TRUE and the necessary information to - * create an instance of it if it was found. - */ -static int findMtypeArg(sipMappedType **mttab, const char *name, size_t len, - sipSigArg *at, int indir) -{ - sipMappedType *mt; - - while ((mt = *mttab++) != NULL) - if (nameEq(mt->mt_name, name, len)) - { - if (indir == 0) - at->atype = mtype_sat; - else if (indir == 1) - at->atype = mtypep_sat; - else - at->atype = unknown_sat; - - at->u.mt = mt; - - return TRUE; - } - - return FALSE; -} - - -/* - * Search for a named enum in a particular module and return the corresponding - * type object. - */ -static PyTypeObject *findEnum(sipExportedModuleDef *emd, const char *name, - size_t len) -{ - int i; - sipEnumDef *ed; - - for (ed = emd->em_enumdefs, i = 0; i < emd->em_nrenums; ++i, ++ed) - { - if (ed->e_cname != NULL) - { - if (!nameEq(ed->e_cname, name, len)) - continue; - } - else if (!sameScopedName(ed->e_name, name, len)) - continue; - - return emd->em_enums[i]; - } - - return NULL; -} - - -/* - * Search for a named enum and return TRUE and the necessary information to - * create an instance of it if it was found. - */ -static int findEnumArg(sipExportedModuleDef *emd, const char *name, size_t len, - sipSigArg *at, int indir) -{ - PyTypeObject *py = findEnum(emd, name, len); - - if (py == NULL) - return FALSE; - - if (indir == 0) - at->atype = enum_sat; - else - at->atype = unknown_sat; - - at->u.et = py; - - return TRUE; -} - - -/* - * Search for a named type and the necessary information to create an instance - * of it. - */ -void sipFindSigArgType(const char *name, size_t len, sipSigArg *at, int indir) -{ - sipExportedModuleDef *em; - sipPyObject *po; - - at->atype = unknown_sat; - - for (em = clientList; em != NULL; em = em->em_next) - { - sipTypedefDef *tdd; - - /* Search for a typedef. */ - if ((tdd = em->em_typedefs) != NULL) - while (tdd->tdd_name != NULL) - { - if (nameEq(tdd->tdd_name, name, len)) - { - sipExportedModuleDef *tem; - const char *tn; - size_t tnlen; - - at->atype = tdd->tdd_type; - - /* Done with the simple cases. */ - if ((tn = tdd->tdd_type_name) == NULL) - return; - - /* - * Find the module that this class, mapped type or enum is - * defined in. - */ - if (tdd->tdd_mod_name == NULL) - tem = em; - else - for (tem = clientList; tem != NULL; tem = tem->em_next) - if (strcmp(tem->em_name, tdd->tdd_mod_name) == 0) - break; - - tnlen = strlen(tn); - - switch (tdd->tdd_type) - { - case class_sat: - findClassArg(tem, tn, tnlen, at, indir); - break; - - case mtype_sat: - findMtypeArg(tem->em_mappedtypes, tn, tnlen, at, indir); - break; - - case enum_sat: - findEnumArg(tem, tn, tnlen, at, indir); - break; - } - - /* We should have found it by now. */ - return; - } - - ++tdd; - } - - /* Search for a class. */ - if (em->em_types != NULL && findClassArg(em, name, len, at, indir)) - return; - - /* Search for a mapped type. */ - if (em->em_mappedtypes != NULL && findMtypeArg(em->em_mappedtypes, name, len, at, indir)) - return; - - /* Search for an enum. */ - if (em->em_enums != NULL && findEnumArg(em, name, len, at, indir)) - return; - } - - /* Search for a dynamically registered int type. */ - for (po = sipRegisteredIntTypes; po != NULL; po = po->next) - { - int i; - - for (i = 0; i < PyTuple_GET_SIZE(po->object); ++i) - { - char *int_nm = PyString_AsString(PyTuple_GET_ITEM(po->object, i)); - - if (int_nm == NULL) - continue; - - if (nameEq(int_nm, name, len)) - { - at->atype = int_sat; - return; - } - } - } -} - - -/* - * Compare a '\0' terminated string with the first len characters of a second - * and return a non-zero value if they are equal. - */ -static int nameEq(const char *with, const char *name, size_t len) -{ - return (strlen(with) == len && strncmp(with, name, len) == 0); -} - - -/* - * Return TRUE if a Python scoped name and a fixed length C++ scoped name - * match. - */ -static int sameScopedName(const char *pyname, const char *name, size_t len) -{ - char ch; - - /* Skip the module name from the Python name. */ - pyname = strchr(pyname, '.') + 1; - - while ((ch = *pyname++) != '\0' && len) - if (ch == '.') - { - if (len < 2 || name[0] != ':' || name[1] != ':') - return FALSE; - - name += 2; - len -= 2; - } - else if (ch == name[0]) - { - ++name; - --len; - } - else - return FALSE; - - return (ch == '\0' && len == 0); -} - - -/* - * Register a Python tuple of type names that will be interpreted as ints if - * they are seen as signal arguments. - */ -static int sip_api_register_int_types(PyObject *args) -{ - sipPyObject *po; - int bad_args = FALSE; - - /* Raise an exception if the arguments are bad. */ - if (PyTuple_Check(args)) - { - int i; - - for (i = 0; i < PyTuple_GET_SIZE(args); ++i) - if (!PyString_Check(PyTuple_GET_ITEM(args, i))) - { - bad_args = TRUE; - break; - } - } - else - bad_args = TRUE; - - if (bad_args) - { - PyErr_SetString(PyExc_TypeError, "all arguments must be strings"); - return -1; - } - - if ((po = sip_api_malloc(sizeof (sipPyObject))) == NULL) - return -1; - - Py_INCREF(args); - - po->object = args; - po->next = sipRegisteredIntTypes; - - sipRegisteredIntTypes = 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; -} - - -/* - * Returns TRUE if the Qt support is present and conforms to the v3.4 or later - * of the SIP API. - */ -static int qt_and_sip_api_3_4(void) -{ - return (sipQtSupport != NULL && sipQObjectClass->type->td_module->em_api_minor >= 4); -} - - -/* - * Visit a slot connected to an object for the cyclic garbage collector. - */ -static int visitSlot(sipSlot *slot, visitproc visit, void *arg) -{ - if (slot->pyobj != NULL && sipLambdaSlot(slot->pyobj)) - return visit(slot->pyobj, arg); - - return 0; -} - - -/* - * Clear a slot if it is a lambda function. - */ -static void clearAnyLambda(sipSlot *slot) -{ - PyObject *lam = slot->pyobj; - - if (lam != NULL && sipLambdaSlot(lam)) - { - /* - * Replace the lambda function with None. We don't use NULL as this - * has another meaning. - */ - Py_INCREF(Py_None); - slot->pyobj = Py_None; - - Py_DECREF(lam); - } -} - - -/* - * Convert a Python object to a character. - */ -static char sip_api_string_as_char(PyObject *obj) -{ - char ch; - - if (parseChar(obj, &ch) < 0) - { - PyErr_SetString(PyExc_ValueError, "string of length 1 expected"); - - return '\0'; - } - - return ch; -} - - -/* - * Parse a character array and return it's address and length. - */ -static int parseCharArray(PyObject *obj, char **ap, int *aszp) -{ - if (obj == Py_None) - { - *ap = NULL; - *aszp = 0; - } - else if (PyString_Check(obj)) - { - *ap = PyString_AS_STRING(obj); - *aszp = (int)PyString_GET_SIZE(obj); - } - else - return -1; - - return 0; -} - - -/* - * Parse a character and return it. - */ -static int parseChar(PyObject *obj, char *ap) -{ - if (!PyString_Check(obj) || PyString_GET_SIZE(obj) != 1) - return -1; - - *ap = *PyString_AS_STRING(obj); - - return 0; -} - - -/* - * Parse a character string and return it. - */ -static int parseCharString(PyObject *obj, char **ap) -{ - if (obj == Py_None) - *ap = NULL; - else if (PyString_Check(obj)) - *ap = PyString_AS_STRING(obj); - else - return -1; - - return 0; -} - - -#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_SetString(PyExc_ValueError, "unicode string of length 1 expected"); - - 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_SetString(PyExc_ValueError, "unicode string expected"); - - return NULL; - } - - return p; -} - - -/* - * Parse a wide character array and return it's address and length. - */ -static int parseWCharArray(PyObject *obj, wchar_t **ap, int *aszp) -{ - if (obj == Py_None) - { - *ap = NULL; - *aszp = 0; - } - else if (PyUnicode_Check(obj)) - { - 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 = (int)ulen; - } - else - return -1; - - return 0; -} - - -/* - * Parse a wide character and return it. - */ -static int parseWChar(PyObject *obj, wchar_t *ap) -{ - if (!PyUnicode_Check(obj) || 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 it. - */ -static int parseWCharString(PyObject *obj, wchar_t **ap) -{ - if (obj == Py_None) - *ap = NULL; - else if (PyUnicode_Check(obj)) - { - 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; - } - else - return -1; - - 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 diff --git a/python/sip/siplib/siplib.sbf b/python/sip/siplib/siplib.sbf deleted file mode 100644 index 2499d1b8..00000000 --- a/python/sip/siplib/siplib.sbf +++ /dev/null @@ -1,16 +0,0 @@ -# This is the build file for the extension module. -# -# Copyright (c) 2007 -# Riverbank Computing Limited <info@riverbankcomputing.co.uk> -# -# 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. -# -# SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -target = sip -sources = siplib.c qtlib.c threads.c objmap.c bool.cpp -headers = sip.h sipint.h diff --git a/python/sip/siplib/threads.c b/python/sip/siplib/threads.c deleted file mode 100644 index c4ee75ff..00000000 --- a/python/sip/siplib/threads.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * 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) 2007 - * Riverbank Computing Limited <info@riverbankcomputing.co.uk> - * - * 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. - * - * 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 *td; - - if ((td = currentThreadDef()) != NULL) - pp = &td->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, sipWrapperType *type, - sipWrapper *owner, int flags) -{ - static PyObject *nullargs = NULL; - - pendingDef old_pending; - PyObject *self; -#ifdef WITH_THREAD - threadDef *td; -#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 ((td = currentThreadDef()) != NULL) - { - old_pending = td->pending; - - td->pending.cpp = cppPtr; - td->pending.owner = owner; - td->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 *)type, nullargs, NULL); - -#ifdef WITH_THREAD - if (td != NULL) - td->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 *td; - - /* Save the thread ID. First, find an empty slot in the list. */ - for (td = threads; td != NULL; td = td->next) - if (td->thr_ident == 0) - break; - - if (td == NULL) - { - td = sip_api_malloc(sizeof (threadDef)); - td->next = threads; - threads = td; - } - - if (td != NULL) - { - td->thr_ident = PyThread_get_thread_ident(); - td->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 *td; - - /* We have the GIL at this point. */ - if ((td = currentThreadDef()) != NULL) - td->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 *td; - long ident = PyThread_get_thread_ident(); - - for (td = threads; td != NULL; td = td->next) - if (td->thr_ident == ident) - break; - - return td; -} - -#endif |