diff --git a/build.py b/build.py index dd366e4c..d6697507 100755 --- a/build.py +++ b/build.py @@ -30,16 +30,16 @@ version2 = "%d.%d" % (version.VER_MAJOR, version.VER_MINOR) version3 = "%d.%d.%d" % (version.VER_MAJOR, version.VER_MINOR, version.VER_RELEASE) version2_nodot = version2.replace(".", "") version3_nodot = version3.replace(".", "") -unstable_series = (version.VER_MINOR % 2) == 1 # is the minor version odd or even +unstable_series = (version.VER_MINOR % 2) == 1 # is the minor version odd or even? isWindows = sys.platform.startswith('win') isDarwin = sys.platform == "darwin" -sipCurrentVersion = '4.12.5-snapshot-de6a700f5faa' +sipCurrentVersion = '4.12.5-snapshot-3a009ee97d60' sipCurrentVersionMD5 = { - 'darwin' : 'fa3b5c21e537be347a39da9f423a8ce7', - 'win32' : 'c8f5188de8d0e19474912718e91515f0', - 'linux2' : '950b92de13f0f9e63f48ec1c2d3bf6fb', + 'darwin' : '5d8ea39022e8daca219e5dc7752b3ebb', + 'win32' : '9e238f429ce2d19cb418aeca1906230c', + 'linux2' : 'e5a3a8a0515d17446bf503a9b49951e9', } toolsURL = 'http://wxpython.org/tools' diff --git a/etg/event.py b/etg/event.py index ad1d2523..0b355c77 100644 --- a/etg/event.py +++ b/etg/event.py @@ -332,11 +332,8 @@ def run(): c.find('wxDropFilesEvent').setCppCode_sip("""\ if (files) { wxStringArrayHolder* holder = new wxStringArrayHolder; - // TODO: if/when sip honors the Transfer annotation then this copy loop - // can be eliminated. Just do holder->m_array = files instead. - holder->m_array = new wxString[noFiles]; - for (int i=0; im_array[i] = files[i]; + holder->m_array = files; + // Make a PyObject for the holder, and transfer its ownership to self. PyObject* pyHolder = sipConvertFromNewType( (void*)holder, sipType_wxStringArrayHolder, (PyObject*)sipSelf); Py_DECREF(pyHolder); diff --git a/sip/siplib/sip.h b/sip/siplib/sip.h index 3fe6414f..5783721b 100644 --- a/sip/siplib/sip.h +++ b/sip/siplib/sip.h @@ -55,7 +55,7 @@ extern "C" { * Define the SIP version number. */ #define SIP_VERSION 0x040c05 -#define SIP_VERSION_STR "4.12.5-snapshot-de6a700f5faa" +#define SIP_VERSION_STR "4.12.5-snapshot-3a009ee97d60" /* @@ -68,9 +68,6 @@ extern "C" { * * History: * - * 8.2 Deprecated the old sip_api_is_py_method(). - * Added the new sip_api_is_py_method(). - * * 8.1 Revised the sipVariableDef structure. * sip_api_get_address() is now part of the public API. * @@ -178,7 +175,7 @@ extern "C" { * 0.0 Original version. */ #define SIP_API_MAJOR_NR 8 -#define SIP_API_MINOR_NR 2 +#define SIP_API_MINOR_NR 1 /* The name of the sip module. */ @@ -1418,7 +1415,7 @@ typedef struct _sipAPIDef { void (*api_bad_class)(const char *classname); void *(*api_get_cpp_ptr)(sipSimpleWrapper *w, const sipTypeDef *td); void *(*api_get_complex_cpp_ptr)(sipSimpleWrapper *w); - PyObject *(*api_is_py_method_old)(sip_gilstate_t *gil, char *pymc, + PyObject *(*api_is_py_method)(sip_gilstate_t *gil, char *pymc, sipSimpleWrapper *sipSelf, const char *cname, const char *mname); void (*api_call_hook)(const char *hookname); void (*api_start_thread)(void); @@ -1457,13 +1454,6 @@ typedef struct _sipAPIDef { * The following are part of the public API. */ void *(*api_get_address)(struct _sipSimpleWrapper *w); - - /* - * The following are not part of the public API. - */ - PyObject *(*api_is_py_method)(sip_gilstate_t *gil, char *pymc, - sipSimpleWrapper * const *sipSelfp, const char *cname, - const char *mname); } sipAPIDef; diff --git a/sip/siplib/siplib.c b/sip/siplib/siplib.c index e134f269..73b320cf 100644 --- a/sip/siplib/siplib.c +++ b/sip/siplib/siplib.c @@ -203,9 +203,6 @@ static void sip_api_abstract_method(const char *classname, const char *method); static void sip_api_bad_class(const char *classname); static void *sip_api_get_complex_cpp_ptr(sipSimpleWrapper *sw); static PyObject *sip_api_is_py_method(sip_gilstate_t *gil, char *pymc, - sipSimpleWrapper * const *sipSelfp, const char *cname, - const char *mname); -static PyObject *sip_api_is_py_method_old(sip_gilstate_t *gil, char *pymc, sipSimpleWrapper *sipSelf, const char *cname, const char *mname); static void sip_api_call_hook(const char *hookname); static void sip_api_raise_unknown_exception(void); @@ -342,7 +339,7 @@ static const sipAPIDef sip_api = { sip_api_bad_class, sip_api_get_cpp_ptr, sip_api_get_complex_cpp_ptr, - sip_api_is_py_method_old, + sip_api_is_py_method, sip_api_call_hook, sip_api_start_thread, sip_api_end_thread, @@ -369,11 +366,7 @@ static const sipAPIDef sip_api = { /* * The following are part of the public API. */ - sip_api_get_address, - /* - * The following are not part of the public API. - */ - sip_api_is_py_method + sip_api_get_address }; @@ -590,6 +583,7 @@ static sipExportedModuleDef *getTypeModule(const sipEncodedTypeDef *enc, static sipTypeDef *getGeneratedType(const sipEncodedTypeDef *enc, sipExportedModuleDef *em); static const sipTypeDef *convertSubClass(const sipTypeDef *td, void **cppPtr); +static int convertPass(const sipTypeDef **tdp, void **cppPtr); static void *getPtrTypeDef(sipSimpleWrapper *self, const sipClassTypeDef **ctd); static int addInstances(PyObject *dict, sipInstancesDef *id); @@ -5218,7 +5212,7 @@ static void callPyDtor(sipSimpleWrapper *self) char pymc = 0; PyObject *meth; - meth = sip_api_is_py_method(&sipGILState, &pymc, &self, NULL, "__dtor__"); + meth = sip_api_is_py_method(&sipGILState, &pymc, self, NULL, "__dtor__"); if (meth != NULL) { @@ -7531,29 +7525,15 @@ static PyObject *getDictFromObject(PyObject *obj) } -/* - * Return a Python reimplementation corresponding to a C/C++ virtual function, - * if any. If one was found then the GIL is acquired. This is deprecated and - * only used by modules generated by an older version. - */ -static PyObject *sip_api_is_py_method_old(sip_gilstate_t *gil, char *pymc, - sipSimpleWrapper *sipSelf, const char *cname, const char *mname) -{ - return sip_api_is_py_method(gil, pymc, &sipSelf, cname, mname); -} - - /* * Return a Python reimplementation corresponding to a C/C++ virtual function, * if any. If one was found then the GIL is acquired. */ static PyObject *sip_api_is_py_method(sip_gilstate_t *gil, char *pymc, - sipSimpleWrapper * const *sipSelfp, const char *cname, - const char *mname) + sipSimpleWrapper *sipSelf, const char *cname, const char *mname) { PyObject *mname_obj, *reimp, *mro, *cls; SIP_SSIZE_T i; - sipSimpleWrapper *sipSelf; /* * This is the most common case (where there is no Python reimplementation) @@ -7566,28 +7546,34 @@ static PyObject *sip_api_is_py_method(sip_gilstate_t *gil, char *pymc, if (sipInterpreter == NULL) return NULL; -#ifdef WITH_THREAD - *gil = PyGILState_Ensure(); -#endif - /* * It's possible that the Python object has been deleted but the underlying * C++ instance is still working and trying to handle virtual functions. * Alternatively, an instance has started handling virtual functions before * its ctor has returned. In either case say there is no Python - * reimplementation. We do this with the GIL in case the object is in the + * reimplementation. + */ + if (sipSelf == NULL) + return NULL; + + /* + * It's possible that the object's type's tp_mro is NULL. A possible + * circumstance is when a type has been created dynamically and the only + * reference to it is the single instance of the type which is in the * process of being garbage collected. */ - if ((sipSelf = *sipSelfp) == NULL) - { -#ifdef WITH_THREAD - PyGILState_Release(*gil); -#endif + cls = (PyObject *)Py_TYPE(sipSelf); + mro = ((PyTypeObject *)cls)->tp_mro; + + if (mro == NULL) return NULL; - } /* Get any reimplementation. */ +#ifdef WITH_THREAD + *gil = PyGILState_Ensure(); +#endif + #if PY_MAJOR_VERSION >= 3 mname_obj = PyUnicode_FromString(mname); #else @@ -7630,8 +7616,6 @@ static PyObject *sip_api_is_py_method(sip_gilstate_t *gil, char *pymc, } } - cls = (PyObject *)Py_TYPE(sipSelf); - mro = ((PyTypeObject *)cls)->tp_mro; assert(PyTuple_Check(mro)); reimp = NULL; @@ -8399,12 +8383,26 @@ static void sip_api_call_hook(const char *hookname) */ static const sipTypeDef *convertSubClass(const sipTypeDef *td, void **cppPtr) { - PyTypeObject *py_type = sipTypeAsPyTypeObject(td); - sipExportedModuleDef *em; - + /* Handle the trivial case. */ if (*cppPtr == NULL) return NULL; + /* Try the conversions until told to stop. */ + while (convertPass(&td, cppPtr)) + ; + + return td; +} + + +/* + * Do a single pass through the available convertors. + */ +static int convertPass(const sipTypeDef **tdp, void **cppPtr) +{ + PyTypeObject *py_type = sipTypeAsPyTypeObject(*tdp); + sipExportedModuleDef *em; + /* * 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 @@ -8419,6 +8417,8 @@ static const sipTypeDef *convertSubClass(const sipTypeDef *td, void **cppPtr) while (scc->scc_convertor != NULL) { + PyTypeObject *base_type = sipTypeAsPyTypeObject(scc->scc_basetype); + /* * The base type is the "root" class that may have a number of * convertors each handling a "branch" of the derived tree of @@ -8428,27 +8428,39 @@ static const sipTypeDef *convertSubClass(const sipTypeDef *td, void **cppPtr) * sub-class of the root, ie. see if the convertor might be able to * convert the target type to something more specific. */ - if (PyType_IsSubtype(py_type, sipTypeAsPyTypeObject(scc->scc_basetype))) + if (PyType_IsSubtype(py_type, base_type)) { void *ptr; - const sipTypeDef *subtype; + const sipTypeDef *sub_td; ptr = cast_cpp_ptr(*cppPtr, py_type, scc->scc_basetype); - subtype = (*scc->scc_convertor)(&ptr); - /* - * We are only interested in types that are not super-classes - * of the target. This happens either because it is in an - * earlier convertor than the one that handles the type or it - * is in a later convertor that handles a different branch of - * the hierarchy. Either way, the ordering of the modules - * ensures that there will be no more than one and that it will - * be the right one. - */ - if (subtype != NULL && !PyType_IsSubtype(py_type, sipTypeAsPyTypeObject(subtype))) + if ((sub_td = (*scc->scc_convertor)(&ptr)) != NULL) { - *cppPtr = ptr; - return subtype; + PyTypeObject *sub_type = sipTypeAsPyTypeObject(sub_td); + + /* + * 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 (!PyType_IsSubtype(py_type, sub_type)) + { + *tdp = sub_td; + *cppPtr = ptr; + + /* + * Finally we allow the convertor to return a type that + * is apparently unrelated to the current convertor. + * This causes the whole process to be restarted with + * the new values. The use case is PyQt's QLayoutItem. + */ + return !PyType_IsSubtype(sub_type, base_type); + } } } @@ -8463,7 +8475,7 @@ static const sipTypeDef *convertSubClass(const sipTypeDef *td, void **cppPtr) * Also we want this function to be safe when a class doesn't have any * convertors. */ - return td; + return FALSE; }