diff --git a/build.py b/build.py index 72e76530..31f935f5 100755 --- a/build.py +++ b/build.py @@ -36,11 +36,11 @@ unstable_series = (version.VER_MINOR % 2) == 1 # is the minor version odd or ev isWindows = sys.platform.startswith('win') isDarwin = sys.platform == "darwin" -sipCurrentVersion = '4.13.1-snapshot-98421b9cc511' +sipCurrentVersion = '4.13.1-snapshot-7ab562ae0e39' sipCurrentVersionMD5 = { - 'darwin' : '1d5ae7c54b768a77d951df3bae15a33e', - 'win32' : 'abe8ff9ff1804f9cf6def83712643187', - 'linux2' : 'fbab55f36f05dfbf31d4968ce187abb8', # TODO: linux build needs updated!! + 'darwin' : '2da0cc2ba853b2787499da0596b4e8ac', + 'win32' : '45673b36d6885632ad0f273c496a1383', + 'linux2' : 'f7971044b97f7fc7650fef2189517937', } toolsURL = 'http://wxpython.org/Phoenix/tools' diff --git a/sip/siplib/objmap.c b/sip/siplib/objmap.c index 1dc49197..9d2c0a7a 100644 --- a/sip/siplib/objmap.c +++ b/sip/siplib/objmap.c @@ -40,6 +40,12 @@ static unsigned long hash_primes[] = { static sipHashEntry *newHashTable(unsigned long); static sipHashEntry *findHashEntry(sipObjectMap *,void *); +static void add_object(sipObjectMap *om, void *addr, sipSimpleWrapper *val); +static void add_aliases(sipObjectMap *om, void *addr, sipSimpleWrapper *val, + const sipClassTypeDef *base_ctd, const sipClassTypeDef *ctd); +static int remove_object(sipObjectMap *om, void *addr, sipSimpleWrapper *val); +static void remove_aliases(sipObjectMap *om, void *addr, sipSimpleWrapper *val, + const sipClassTypeDef *base_ctd, const sipClassTypeDef *ctd); static void reorganiseMap(sipObjectMap *om); static void *getUnguardedPointer(sipSimpleWrapper *w); @@ -115,6 +121,10 @@ sipSimpleWrapper *sipOMFindObject(sipObjectMap *om, void *key, /* Go through each wrapped object at this address. */ for (sw = he->first; sw != NULL; sw = sw->next) { + sipSimpleWrapper *unaliased; + + unaliased = (sipIsAlias(sw) ? (sipSimpleWrapper *)sw->data : sw); + /* * If the reference count is 0 then it is in the process of being * deleted, so ignore it. It's not completely clear how this can @@ -122,19 +132,19 @@ sipSimpleWrapper *sipOMFindObject(sipObjectMap *om, void *key, * code is being re-entered (and there are guards in place to prevent * this). */ - if (Py_REFCNT(sw) == 0) + if (Py_REFCNT(unaliased) == 0) continue; /* Ignore it if the C/C++ address is no longer valid. */ - if (sip_api_get_address(sw) == NULL) + if (sip_api_get_address(unaliased) == NULL) continue; /* * If this wrapped object is of the given type, or a sub-type of it, * then we assume it is the same C++ object. */ - if (PyObject_TypeCheck(sw, py_type)) - return sw; + if (PyObject_TypeCheck(unaliased, py_type)) + return unaliased; } return NULL; @@ -146,7 +156,82 @@ sipSimpleWrapper *sipOMFindObject(sipObjectMap *om, void *key, */ void sipOMAddObject(sipObjectMap *om, sipSimpleWrapper *val) { - sipHashEntry *he = findHashEntry(om, getUnguardedPointer(val)); + void *addr = getUnguardedPointer(val); + const sipClassTypeDef *base_ctd; + + /* Add the object. */ + add_object(om, addr, val); + + /* Add any aliases. */ + base_ctd = (const sipClassTypeDef *)((sipWrapperType *)Py_TYPE(val))->type; + add_aliases(om, addr, val, base_ctd, base_ctd); +} + + +/* + * Add an alias for any address that is different when cast to a super-type. + */ +static void add_aliases(sipObjectMap *om, void *addr, sipSimpleWrapper *val, + const sipClassTypeDef *base_ctd, const sipClassTypeDef *ctd) +{ + const sipEncodedTypeDef *sup; + + /* See if there are any super-classes. */ + if ((sup = ctd->ctd_supers) != NULL) + { + sipClassTypeDef *sup_ctd = sipGetGeneratedClassType(sup, ctd); + + /* Recurse up the hierachy for the first super-class. */ + add_aliases(om, addr, val, base_ctd, sup_ctd); + + /* + * We only check for aliases for subsequent super-classes because the + * first one can never need one. + */ + while (!sup++->sc_flag) + { + void *sup_addr; + + sup_ctd = sipGetGeneratedClassType(sup, ctd); + + /* Recurse up the hierachy for the remaining super-classes. */ + add_aliases(om, addr, val, base_ctd, sup_ctd); + + sup_addr = (*base_ctd->ctd_cast)(addr, sup_ctd); + + if (sup_addr != addr) + { + sipSimpleWrapper *alias; + + /* Note that we silently ignore errors. */ + if ((alias = sip_api_malloc(sizeof (sipSimpleWrapper))) != NULL) + { + /* + * An alias is basically a bit-wise copy of the Python + * object but only to ensure the fields we are subverting + * are in the right place. An alias should never be passed + * to the Python API. + */ + *alias = *val; + + alias->flags = (val->flags & SIP_SHARE_MAP) | SIP_ALIAS; + alias->data = val; + alias->next = NULL; + + add_object(om, sup_addr, alias); + } + } + } + } +} + + +/* + * Add a wrapper (which may be an alias) to the map. + */ +static void add_object(sipObjectMap *om, void *addr, sipSimpleWrapper *val) +{ + sipHashEntry *he = findHashEntry(om, addr); /* * If the bucket is in use then we appear to have several objects at the @@ -196,11 +281,13 @@ void sipOMAddObject(sipObjectMap *om, sipSimpleWrapper *val) /* See if the bucket was unused or stale. */ if (he->key == NULL) { - he->key = getUnguardedPointer(val); + he->key = addr; om->unused--; } else + { om->stale--; + } /* Add the rest of the new value. */ he->first = val; @@ -261,9 +348,8 @@ static void reorganiseMap(sipObjectMap *om) */ int sipOMRemoveObject(sipObjectMap *om, sipSimpleWrapper *val) { - sipHashEntry *he; - sipSimpleWrapper **swp; void *addr; + const sipClassTypeDef *base_ctd; /* Handle the trivial case. */ if (sipNotInMap(val)) @@ -272,12 +358,89 @@ int sipOMRemoveObject(sipObjectMap *om, sipSimpleWrapper *val) if ((addr = getUnguardedPointer(val)) == NULL) return 0; - he = findHashEntry(om, addr); + /* Remove any aliases. */ + base_ctd = (const sipClassTypeDef *)((sipWrapperType *)Py_TYPE(val))->type; + remove_aliases(om, addr, val, base_ctd, base_ctd); + + /* Remove the object. */ + return remove_object(om, addr, val); +} + + +/* + * Remove an alias for any address that is different when cast to a super-type. + */ +static void remove_aliases(sipObjectMap *om, void *addr, sipSimpleWrapper *val, + const sipClassTypeDef *base_ctd, const sipClassTypeDef *ctd) +{ + const sipEncodedTypeDef *sup; + + /* See if there are any super-classes. */ + if ((sup = ctd->ctd_supers) != NULL) + { + sipClassTypeDef *sup_ctd = sipGetGeneratedClassType(sup, ctd); + + /* Recurse up the hierachy for the first super-class. */ + remove_aliases(om, addr, val, base_ctd, sup_ctd); + + /* + * We only check for aliases for subsequent super-classes because the + * first one can never need one. + */ + while (!sup++->sc_flag) + { + void *sup_addr; + + sup_ctd = sipGetGeneratedClassType(sup, ctd); + + /* Recurse up the hierachy for the remaining super-classes. */ + remove_aliases(om, addr, val, base_ctd, sup_ctd); + + sup_addr = (*base_ctd->ctd_cast)(addr, sup_ctd); + + if (sup_addr != addr) + remove_object(om, sup_addr, val); + } + } +} + + +/* + * Remove a wrapper from the map. + */ +static int remove_object(sipObjectMap *om, void *addr, sipSimpleWrapper *val) +{ + sipHashEntry *he = findHashEntry(om, addr); + sipSimpleWrapper **swp; for (swp = &he->first; *swp != NULL; swp = &(*swp)->next) - if (*swp == val) + { + sipSimpleWrapper *sw, *next; + int do_remove; + + sw = *swp; + next = sw->next; + + if (sipIsAlias(sw)) { - *swp = val->next; + if (sw->data == val) + { + sip_api_free(sw); + do_remove = TRUE; + } + else + { + do_remove = FALSE; + } + } + else + { + do_remove = (sw == val); + } + + if (do_remove) + { + *swp = next; /* * If the bucket is now empty then count it as stale. Note that we @@ -292,6 +455,7 @@ int sipOMRemoveObject(sipObjectMap *om, sipSimpleWrapper *val) return 0; } + } return -1; } diff --git a/sip/siplib/sip.h b/sip/siplib/sip.h index b15c8df5..11d259ee 100644 --- a/sip/siplib/sip.h +++ b/sip/siplib/sip.h @@ -54,8 +54,8 @@ extern "C" { /* * Define the SIP version number. */ -#define SIP_VERSION 0x040c05 -#define SIP_VERSION_STR "4.12.5-snapshot-4eba42cb2457" +#define SIP_VERSION 0x040d01 +#define SIP_VERSION_STR "4.13.1-snapshot-7ab562ae0e39" /* @@ -1506,13 +1506,14 @@ typedef struct _sipQtAPI { /* * Useful macros, not part of the public API. */ -#define SIP_PY_OWNED 0x0004 /* Owned by Python. */ +#define SIP_PY_OWNED 0x0004 /* If 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_NOT_IN_MAP 0x0020 /* If Python object is not in the map. */ #define SIP_SHARE_MAP 0x0040 /* If the map slot might be occupied. */ #define SIP_CPP_HAS_REF 0x0080 /* If C/C++ has a reference. */ #define SIP_POSSIBLE_PROXY 0x0100 /* If there might be a proxy slot. */ +#define SIP_ALIAS 0x0200 /* If it is an alias. */ #define sipIsPyOwned(w) ((w)->flags & SIP_PY_OWNED) #define sipSetPyOwned(w) ((w)->flags |= SIP_PY_OWNED) @@ -1527,6 +1528,7 @@ typedef struct _sipQtAPI { #define sipResetCppHasRef(w) ((w)->flags &= ~SIP_CPP_HAS_REF) #define sipPossibleProxy(w) ((w)->flags & SIP_POSSIBLE_PROXY) #define sipSetPossibleProxy(w) ((w)->flags |= SIP_POSSIBLE_PROXY) +#define sipIsAlias(w) ((w)->flags & SIP_ALIAS) #define SIP_TYPE_TYPE_MASK 0x0007 /* The type type mask. */ diff --git a/sip/siplib/sipint.h b/sip/siplib/sipint.h index 4aa6e972..990ba5eb 100644 --- a/sip/siplib/sipint.h +++ b/sip/siplib/sipint.h @@ -124,6 +124,8 @@ int sip_api_save_slot(sipSlot *sp, PyObject *rxObj, const char *slot); /* * These are not part of the SIP API but are used within the SIP module. */ +sipClassTypeDef *sipGetGeneratedClassType(sipEncodedTypeDef *enc, + const sipClassTypeDef *ctd); void sipSaveMethod(sipPyMethod *pm,PyObject *meth); void *sipGetPending(sipWrapper **op, int *fp); PyObject *sipWrapSimpleInstance(void *cppPtr, const sipTypeDef *td, diff --git a/sip/siplib/siplib.c b/sip/siplib/siplib.c index 73b320cf..8962c0a9 100644 --- a/sip/siplib/siplib.c +++ b/sip/siplib/siplib.c @@ -8605,6 +8605,16 @@ static sipTypeDef *getGeneratedType(const sipEncodedTypeDef *enc, } +/* + * Return the generated class type structure of a class's super-class. + */ +sipClassTypeDef *sipGetGeneratedClassType(sipEncodedTypeDef *enc, + const sipClassTypeDef *ctd) +{ + return (sipClassTypeDef *)getGeneratedType(enc, ctd->ctd_base.td_module); +} + + /* * Find a particular slot function for a type. */ @@ -8631,19 +8641,15 @@ static void *findSlot(PyObject *self, sipPySlotType st) /* Search any super-types. */ if ((sup = ctd->ctd_supers) != NULL) - { - sipClassTypeDef *sup_ctd; - do { - sup_ctd = (sipClassTypeDef *)getGeneratedType(sup, - ctd->ctd_base.td_module); + sipClassTypeDef *sup_ctd = sipGetGeneratedClassType(sup, + ctd); if (sup_ctd->ctd_pyslots != NULL) slot = findSlotInType(sup_ctd->ctd_pyslots, st); } while (slot == NULL && !sup++->sc_flag); - } } } else @@ -9176,7 +9182,7 @@ static int sipSimpleWrapper_traverse(sipSimpleWrapper *self, visitproc visit, if ((sup = ctd->ctd_supers) != NULL) do - sup_ctd = (sipClassTypeDef *)getGeneratedType(sup, ctd->ctd_base.td_module); + sup_ctd = sipGetGeneratedClassType(sup, ctd); while (sup_ctd->ctd_traverse == NULL && !sup++->sc_flag); }