From f786e915f2f26785de87672788e47a1ddee0332c Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 22 Nov 2021 16:24:33 +0100 Subject: libpyside6: Add a convenience function to convert a PyObject * to a QObject * Task-number: PYSIDE-1709 Change-Id: I137d7fd3ac84f50bb6a799e27e07b7523d943812 Reviewed-by: Christian Tismer (cherry picked from commit a34622f8098d67c706148eac506460fc65a6401f) Reviewed-by: Qt Cherry-pick Bot --- .../PySide6/QtQml/pysideqmlregistertype.cpp | 11 ++---- sources/pyside6/libpyside/pyside.cpp | 42 +++++++++++++++++----- sources/pyside6/libpyside/pyside.h | 3 ++ 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/sources/pyside6/PySide6/QtQml/pysideqmlregistertype.cpp b/sources/pyside6/PySide6/QtQml/pysideqmlregistertype.cpp index b769a1eb9..f7f1b2375 100644 --- a/sources/pyside6/PySide6/QtQml/pysideqmlregistertype.cpp +++ b/sources/pyside6/PySide6/QtQml/pysideqmlregistertype.cpp @@ -295,15 +295,10 @@ int PySide::qmlRegisterSingletonInstance(PyObject *pyObj, const char *uri, int v if (!isQObjectDerived(pyObjType, true)) return -1; - // Check if the instance object derives from QObject - PyTypeObject *typeInstanceObject = instanceObject->ob_type; - - if (!isQObjectDerived(typeInstanceObject, true)) - return -1; - // Convert the instanceObject (PyObject) into a QObject - QObject *instanceQObject = reinterpret_cast( - Object::cppPointer(reinterpret_cast(instanceObject), qObjectType())); + QObject *instanceQObject = PySide::convertToQObject(instanceObject, true); + if (instanceQObject == nullptr) + return -1; // Create Singleton Functor to pass the QObject to the Type registration step // similarly to the case when we have a callback diff --git a/sources/pyside6/libpyside/pyside.cpp b/sources/pyside6/libpyside/pyside.cpp index 5c3b0f3af..4769ea86d 100644 --- a/sources/pyside6/libpyside/pyside.cpp +++ b/sources/pyside6/libpyside/pyside.cpp @@ -649,18 +649,44 @@ bool registerInternalQtConf() return isRegistered; } -bool isQObjectDerived(PyTypeObject *pyType, bool raiseError) { - static PyTypeObject *qobjectType = Shiboken::Conversions::getPythonTypeObject("QObject*"); +static PyTypeObject *qobjectType() +{ + static PyTypeObject * const result = Shiboken::Conversions::getPythonTypeObject("QObject*"); + return result; +} - if (!PyType_IsSubtype(pyType, qobjectType)) { - if (raiseError) - PyErr_Format(PyExc_TypeError, "A type inherited from %s expected, got %s.", - qobjectType->tp_name, pyType->tp_name); - return false; +bool isQObjectDerived(PyTypeObject *pyType, bool raiseError) +{ + const bool result = PyType_IsSubtype(pyType, qobjectType()); + if (!result && raiseError) { + PyErr_Format(PyExc_TypeError, "A type inherited from %s expected, got %s.", + qobjectType()->tp_name, pyType->tp_name); } - return true; + return result; } +QObject *convertToQObject(PyObject *object, bool raiseError) +{ + if (object == nullptr) { + if (raiseError) + PyErr_Format(PyExc_TypeError, "None passed for QObject"); + return nullptr; + } + + if (!isQObjectDerived(Py_TYPE(object), raiseError)) + return nullptr; + + auto *sbkObject = reinterpret_cast(object); + auto *ptr = Shiboken::Object::cppPointer(sbkObject, qobjectType()); + if (ptr == nullptr) { + if (raiseError) { + PyErr_Format(PyExc_TypeError, "Conversion of %s to QObject failed.", + Py_TYPE(object)->tp_name); + } + return nullptr; + } + return reinterpret_cast(ptr); +} } //namespace PySide diff --git a/sources/pyside6/libpyside/pyside.h b/sources/pyside6/libpyside/pyside.h index 3b1c85333..39fbef3cc 100644 --- a/sources/pyside6/libpyside/pyside.h +++ b/sources/pyside6/libpyside/pyside.h @@ -111,6 +111,9 @@ PYSIDE_API std::size_t getSizeOfQObject(PyTypeObject *type); */ PYSIDE_API bool isQObjectDerived(PyTypeObject *pyType, bool raiseError); +/// Convenience to convert a PyObject to QObject +PYSIDE_API QObject *convertToQObject(PyObject *object, bool raiseError); + typedef void (*CleanupFunction)(void); /** -- cgit v1.2.3