From d147d5473289763049ffa6843d00aaf3766b6e4e Mon Sep 17 00:00:00 2001 From: Jan Plath Date: Fri, 30 Jan 2026 14:41:57 +0100 Subject: [PATCH] Fix invalid handling of alreadyAllocatedCPPObject in PythonQtConv::ConvertPythonToQt --- src/PythonQtConversion.cpp | 32 +++++++------------------------- src/PythonQtConversion.h | 1 + src/PythonQtMisc.h | 29 +++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/PythonQtConversion.cpp b/src/PythonQtConversion.cpp index 96da8be47..3021a04c5 100644 --- a/src/PythonQtConversion.cpp +++ b/src/PythonQtConversion.cpp @@ -592,24 +592,21 @@ void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& i { QByteArray bytes = PyObjGetBytesAllowString(obj, strict, ok); if (ok) { - PythonQtArgumentFrame_ADD_VARIANT_VALUE_IF_NEEDED(alreadyAllocatedCPPObject, frame, QVariant(bytes), ptr); - ptr = (void*)((QVariant*)ptr)->constData(); + ptr = frame->establishPersistentPtr(alreadyAllocatedCPPObject, bytes); } } break; case QMetaType::QString: { QString str = PyObjGetString(obj, strict, ok); if (ok) { - PythonQtArgumentFrame_ADD_VARIANT_VALUE_IF_NEEDED(alreadyAllocatedCPPObject, frame, QVariant(str), ptr); - ptr = (void*)((QVariant*)ptr)->constData(); + ptr = frame->establishPersistentPtr(alreadyAllocatedCPPObject, str); } } break; case QMetaType::QStringList: { QStringList l = PyObjToStringList(obj, strict, ok); if (ok) { - PythonQtArgumentFrame_ADD_VARIANT_VALUE_IF_NEEDED(alreadyAllocatedCPPObject, frame, QVariant(l), ptr); - ptr = (void*)((QVariant*)ptr)->constData(); + ptr = frame->establishPersistentPtr(alreadyAllocatedCPPObject, l); } } break; @@ -649,7 +646,7 @@ void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& i QString str = PyObjGetString(obj, strict, ok); if (ok) { void* ptr2 = nullptr; - PythonQtArgumentFrame_ADD_VARIANT_VALUE_IF_NEEDED(nullptr, frame, QVariant(str), ptr2); + PythonQtArgumentFrame_ADD_VARIANT_VALUE(frame, QVariant(str), ptr2); PythonQtArgumentFrame_ADD_VARIANT_VALUE_IF_NEEDED(alreadyAllocatedCPPObject, frame, QVariant::fromValue(QStringRef((const QString*)((QVariant*)ptr2)->constData())), ptr); ptr = (void*)((QVariant*)ptr)->constData(); @@ -663,12 +660,7 @@ void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& i // Handle QStringView, which needs a reference to a persistent QString QString str = PyObjGetString(obj, strict, ok); if (ok) { - void* ptr2 = nullptr; - PythonQtArgumentFrame_ADD_VARIANT_VALUE_IF_NEEDED(nullptr, frame, QVariant(str), ptr2); - PythonQtArgumentFrame_ADD_VARIANT_VALUE_IF_NEEDED(alreadyAllocatedCPPObject, frame, - QVariant::fromValue(QStringView(*((const QString*)((QVariant*)ptr2)->constData()))), ptr); - ptr = (void*)((QVariant*)ptr)->constData(); - return ptr; + return frame->establishPersistentViewPtr(alreadyAllocatedCPPObject, str); } else { return nullptr; } @@ -676,12 +668,7 @@ void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& i // Handle QAnyStringView, which needs a reference to a persistent QString QString str = PyObjGetString(obj, strict, ok); if (ok) { - void* ptr2 = nullptr; - PythonQtArgumentFrame_ADD_VARIANT_VALUE_IF_NEEDED(nullptr, frame, QVariant(str), ptr2); - PythonQtArgumentFrame_ADD_VARIANT_VALUE_IF_NEEDED(alreadyAllocatedCPPObject, frame, - QVariant::fromValue(QAnyStringView(*((const QString*)((QVariant*)ptr2)->constData()))), ptr); - ptr = (void*)((QVariant*)ptr)->constData(); - return ptr; + return frame->establishPersistentViewPtr(alreadyAllocatedCPPObject, str); } else { return nullptr; } @@ -689,12 +676,7 @@ void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& i // Handle QByteArrayView, which needs a reference to a persistent QByteArray QByteArray ba = PyObjGetBytesAllowString(obj, strict, ok); if (ok) { - void* ptr2 = nullptr; - PythonQtArgumentFrame_ADD_VARIANT_VALUE_IF_NEEDED(nullptr, frame, QVariant(ba), ptr2); - PythonQtArgumentFrame_ADD_VARIANT_VALUE_IF_NEEDED(alreadyAllocatedCPPObject, frame, - QVariant::fromValue(QByteArrayView(*((const QByteArray*)((QVariant*)ptr2)->constData()))), ptr); - ptr = (void*)((QVariant*)ptr)->constData(); - return ptr; + return frame->establishPersistentViewPtr(alreadyAllocatedCPPObject, ba); } else { return nullptr; } diff --git a/src/PythonQtConversion.h b/src/PythonQtConversion.h index 2460876ab..f67d0a738 100644 --- a/src/PythonQtConversion.h +++ b/src/PythonQtConversion.h @@ -122,6 +122,7 @@ class PYTHONQT_EXPORT PythonQtConv static PyObject* ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data); //! convert python object to Qt (according to the given parameter) and if the conversion should be strict (classInfo is currently not used anymore) + //! If an alreadyAllocatedCPPObject is used it must have the same type as given by info.typeId static void* ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* classInfo, void* alreadyAllocatedCPPObject, PythonQtArgumentFrame* frame = nullptr); diff --git a/src/PythonQtMisc.h b/src/PythonQtMisc.h index 5c8a70b00..abc824163 100644 --- a/src/PythonQtMisc.h +++ b/src/PythonQtMisc.h @@ -121,6 +121,35 @@ class PythonQtArgumentFrame //! Get next pointer to a POD. quint64* nextPODPtr(); + template + void* establishPersistentPtr(void* alreadyAllocatedPtr, const Class& value) + { + if (alreadyAllocatedPtr) { + *reinterpret_cast(alreadyAllocatedPtr) = value; + return alreadyAllocatedPtr; + } else { + QVariant* item = nextVariantPtr(); + *item = QVariant(value); + return const_cast(item->constData()); + } + } + + template + void* establishPersistentViewPtr(void* alreadyAllocatedPtr, const Class& value) + { + QVariant* itemStore = nextVariantPtr(); + *itemStore = QVariant(value); + if (alreadyAllocatedPtr) { + *reinterpret_cast(alreadyAllocatedPtr) = + ViewClass(*reinterpret_cast(itemStore->constData())); + return alreadyAllocatedPtr; + } else { + QVariant* item = nextVariantPtr(); + *item = QVariant::fromValue(ViewClass(*reinterpret_cast(itemStore->constData()))); + return const_cast(item->constData()); + } + } + private: PythonQtArgumentFrame(); ~PythonQtArgumentFrame();