diff options
Diffstat (limited to 'sources/shiboken6/libshiboken/basewrapper.cpp')
-rw-r--r-- | sources/shiboken6/libshiboken/basewrapper.cpp | 39 |
1 files changed, 32 insertions, 7 deletions
diff --git a/sources/shiboken6/libshiboken/basewrapper.cpp b/sources/shiboken6/libshiboken/basewrapper.cpp index 62e2df2cf..7f927523a 100644 --- a/sources/shiboken6/libshiboken/basewrapper.cpp +++ b/sources/shiboken6/libshiboken/basewrapper.cpp @@ -95,6 +95,13 @@ static void SbkObjectTypeDealloc(PyObject *pyObj); static PyObject *SbkObjectTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *kwds); static SelectableFeatureHook SelectFeatureSet = nullptr; +static DestroyQAppHook DestroyQApplication = nullptr; + +// PYSIDE-1470: Provide a hook to kill an Application from Shiboken. +void setDestroyQApplication(DestroyQAppHook func) +{ + DestroyQApplication = func; +} static PyObject *Sbk_TypeGet___dict__(PyTypeObject *type, void *context); // forward @@ -457,6 +464,12 @@ PyObject *MakeQAppWrapper(PyTypeObject *type) // object already has a reference from PyObject_GC_New. But this is // exactly the needed reference that keeps qApp alive from alone! Py_INCREF(qApp_curr); + // PYSIDE-1470: As a side effect, the interactive "_" variable tends to + // create reference cycles. It was found when using gc.collect(). But using + // PyGC_collect() inside the C code had no effect in the interactive shell. + // The cycle exists only in the eval loop of the interpreter! + if (PyDict_GetItem(builtins, Shiboken::PyName::underscore())) + PyDict_SetItem(builtins, Shiboken::PyName::underscore(), Py_None); return qApp_curr; } @@ -673,7 +686,12 @@ PyObject *SbkObjectTpNew(PyTypeObject *subtype, PyObject *, PyObject *) PyObject *SbkQAppTpNew(PyTypeObject *subtype, PyObject *, PyObject *) { auto self = reinterpret_cast<SbkObject *>(MakeQAppWrapper(subtype)); - return self == nullptr ? nullptr : _setupNew(self, subtype); + if (self == nullptr) + return nullptr; + auto ret = _setupNew(self, subtype); + auto priv = self->d; + priv->isQAppSingleton = 1; + return ret; } PyObject *SbkDummyNew(PyTypeObject *type, PyObject *, PyObject *) @@ -1154,6 +1172,12 @@ bool wasCreatedByPython(SbkObject *pyObj) void callCppDestructors(SbkObject *pyObj) { + auto priv = pyObj->d; + if (priv->isQAppSingleton && DestroyQApplication) { + // PYSIDE-1470: Allow to destroy the application from Shiboken. + DestroyQApplication(); + return; + } PyTypeObject *type = Py_TYPE(pyObj); SbkObjectTypePrivate *sotp = PepType_SOTP(type); if (sotp->is_multicpp) { @@ -1166,18 +1190,19 @@ void callCppDestructors(SbkObject *pyObj) sotp->cpp_dtor(pyObj->d->cptr[0]); } + if (priv->validCppObject && priv->containsCppWrapper) { + BindingManager::instance().releaseWrapper(pyObj); + } + /* invalidate needs to be called before deleting pointer array because it needs to delete entries for them from the BindingManager hash table; also release wrapper explicitly if object contains C++ wrapper because invalidate doesn't */ invalidate(pyObj); - if (pyObj->d->validCppObject && pyObj->d->containsCppWrapper) { - BindingManager::instance().releaseWrapper(pyObj); - } - delete[] pyObj->d->cptr; - pyObj->d->cptr = nullptr; - pyObj->d->validCppObject = false; + delete[] priv->cptr; + priv->cptr = nullptr; + priv->validCppObject = false; } bool hasOwnership(SbkObject *pyObj) |