diff options
author | John Ehresman <jpe@wingware.com> | 2012-12-20 17:26:29 -0500 |
---|---|---|
committer | Hugo Parente Lima <hugo.lima@openbossa.org> | 2012-12-21 15:29:41 +0100 |
commit | b3669dca4e4321b204d10b06018d35900b1847ee (patch) | |
tree | 3578aa3a0250c1a90599b54262b0b911c95b71ca /libpyside | |
parent | aeccd2a05bba8c94a3a338370f16af1d545e8abd (diff) |
Use QObject property to invalidate wrapper before deletion.
Define a getWrapperForQObject function to create / find
wrappers for QObject derived objects. It sets a property
so that an invalidate function can be called when the QObject
property is cleared in the QObject destructor after all destroyed
signal handlers have been called. Requires a change to shiboken
to generate calls to the getWrapperForQObject function.
Change-Id: I4ed548af114bf7176e8e8255a3ea70549c35d74c
Reviewed-by: Hugo Parente Lima <hugo.lima@openbossa.org>
Diffstat (limited to 'libpyside')
-rw-r--r-- | libpyside/pyside.cpp | 52 | ||||
-rw-r--r-- | libpyside/pyside.h | 2 |
2 files changed, 54 insertions, 0 deletions
diff --git a/libpyside/pyside.cpp b/libpyside/pyside.cpp index 0d96f9530..a71b139a1 100644 --- a/libpyside/pyside.cpp +++ b/libpyside/pyside.cpp @@ -36,6 +36,7 @@ #include <basewrapper.h> #include <conversions.h> #include <sbkconverter.h> +#include <gilstate.h> #include <typeresolver.h> #include <bindingmanager.h> #include <algorithm> @@ -44,6 +45,7 @@ #include <QStack> #include <QCoreApplication> #include <QDebug> +#include <QSharedPointer> static QStack<PySide::CleanupFunction> cleanupFunctionList; static void* qobjectNextAddr; @@ -293,5 +295,55 @@ void setNextQObjectMemoryAddr(void* addr) qobjectNextAddr = addr; } +} // namespace PySide + +// A QSharedPointer is used with a deletion function to invalidate a pointer +// when the property value is cleared. This should be a QSharedPointer with +// a void* pointer, but that isn't allowed +typedef char any_t; +Q_DECLARE_METATYPE(QSharedPointer<any_t>); + +namespace PySide +{ + +static void invalidatePtr(any_t* object) +{ + Shiboken::GilState state; + + SbkObject* wrapper = Shiboken::BindingManager::instance().retrieveWrapper(object); + if (wrapper != NULL) + Shiboken::BindingManager::instance().releaseWrapper(wrapper); +} + +static const char invalidatePropertyName[] = "_PySideInvalidatePtr"; + +PyObject* getWrapperForQObject(QObject* cppSelf, SbkObjectType* sbk_type) +{ + PyObject* pyOut = (PyObject*)Shiboken::BindingManager::instance().retrieveWrapper(cppSelf); + if (pyOut) { + Py_INCREF(pyOut); + return pyOut; + } + + // Setting the property will trigger an QEvent notification, which may call into + // code that creates the wrapper so only set the property if it isn't already + // set and check if it's created after the set call + QVariant existing = cppSelf->property(invalidatePropertyName); + if (!existing.isValid()) { + QSharedPointer<any_t> shared_with_del((any_t*)cppSelf, invalidatePtr); + cppSelf->setProperty(invalidatePropertyName, QVariant::fromValue(shared_with_del)); + pyOut = (PyObject*)Shiboken::BindingManager::instance().retrieveWrapper(cppSelf); + if (pyOut) { + Py_INCREF(pyOut); + return pyOut; + } + } + + const char* typeName = typeid(*cppSelf).name(); + pyOut = Shiboken::Object::newObject(sbk_type, cppSelf, false, false, typeName); + + return pyOut; +} + } //namespace PySide diff --git a/libpyside/pyside.h b/libpyside/pyside.h index 779c630a9..35cd36459 100644 --- a/libpyside/pyside.h +++ b/libpyside/pyside.h @@ -117,6 +117,8 @@ PYSIDE_API bool inherits(PyTypeObject* self, const char* class_name); PYSIDE_API void* nextQObjectMemoryAddr(); PYSIDE_API void setNextQObjectMemoryAddr(void* addr); +PYSIDE_API PyObject* getWrapperForQObject(QObject* cppSelf, SbkObjectType* sbk_type); + } //namespace PySide |