aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <[email protected]>2025-02-03 11:47:17 +0100
committerFriedemann Kleint <[email protected]>2025-02-11 15:40:44 +0100
commitc1b62556bffbdd2b5e5eecc790ec4732b93e05a1 (patch)
treee11589a692706b59a70ebcf41e93df07f2db2573
parenta7b1ef20fe791ac6bec92d1f05904ff14bc34e5b (diff)
Fix crash of signals with object-type parameter being passed by const-ref
Add a further indirection in callPythonMetaMethodHelper() when only a pointer conversion is available for a const-ref parameter. Task-number: PYSIDE-3004 Change-Id: I6ec7c5a9d4d30c8e4973ec79534d5f3eb3bf8204 Reviewed-by: Shyamnath Premnadh <[email protected]>
-rw-r--r--sources/pyside6/libpyside/signalmanager.cpp11
-rw-r--r--sources/pyside6/tests/pysidetest/signalemissionfrompython_test.py13
-rw-r--r--sources/pyside6/tests/pysidetest/testobject.cpp5
-rw-r--r--sources/pyside6/tests/pysidetest/testobject.h3
4 files changed, 29 insertions, 3 deletions
diff --git a/sources/pyside6/libpyside/signalmanager.cpp b/sources/pyside6/libpyside/signalmanager.cpp
index 744b77b51..72a427641 100644
--- a/sources/pyside6/libpyside/signalmanager.cpp
+++ b/sources/pyside6/libpyside/signalmanager.cpp
@@ -464,16 +464,21 @@ static int callPythonMetaMethodHelper(const QByteArrayList &paramTypes,
const char *returnType /* = nullptr */,
void **args, PyObject *pyCallable)
{
+ using SpecificConverter = Shiboken::Conversions::SpecificConverter;
const qsizetype argsSize = paramTypes.size();
Shiboken::AutoDecRef preparedArgs(PyTuple_New(argsSize));
for (qsizetype i = 0; i < argsSize; ++i) {
void *data = args[i + 1];
- auto param = paramTypes.at(i);
- Shiboken::Conversions::SpecificConverter converter(param.constData());
+ const auto &param = paramTypes.at(i);
+ SpecificConverter converter(param.constData());
if (!converter.isValid())
return CallResult::CallArgumentError + int(i);
- PyTuple_SetItem(preparedArgs, i, converter.toPython(data));
+ // Only pointer conversion available for const-ref - add indirection
+ const bool valueToPtr = converter.conversionType() == SpecificConverter::PointerConversion
+ && !param.endsWith('*') && param != "PyObject"_ba;
+ auto *src = valueToPtr ? &data : data;
+ PyTuple_SetItem(preparedArgs, i, converter.toPython(src));
}
QScopedPointer<Shiboken::Conversions::SpecificConverter> retConverter;
diff --git a/sources/pyside6/tests/pysidetest/signalemissionfrompython_test.py b/sources/pyside6/tests/pysidetest/signalemissionfrompython_test.py
index 34b8f7f62..64147e15e 100644
--- a/sources/pyside6/tests/pysidetest/signalemissionfrompython_test.py
+++ b/sources/pyside6/tests/pysidetest/signalemissionfrompython_test.py
@@ -27,6 +27,11 @@ class Receiver(QObject):
def __init__(self, p=None):
super().__init__(p)
self.received_handle = -1
+ self.received_name = ''
+
+ @Slot(QObject)
+ def slotObjectByConstRef(self, o):
+ self.received_name = o.objectName()
@Slot(Connection)
def connectionSlot(self, c):
@@ -37,7 +42,9 @@ class SignalEmissionFromPython(unittest.TestCase):
def setUp(self):
self.obj1 = TestObject(0)
+ self.obj1.setObjectName('obj1')
self.obj2 = TestObject(0)
+ self.obj2.setObjectName('obj2')
self.one_called = 0
self.two_called = 0
@@ -114,6 +121,12 @@ class SignalEmissionFromPython(unittest.TestCase):
self.assertEqual(self.one_called, 1)
self.assertEqual(self.two_called, 2)
+ def testSignalObjectByConstRef(self):
+ receiver = Receiver()
+ self.obj1.objectByConstRef.connect(receiver.slotObjectByConstRef)
+ self.obj1.emitObjectByConstRef()
+ self.assertEqual(receiver.received_name, 'obj1')
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/testobject.cpp b/sources/pyside6/tests/pysidetest/testobject.cpp
index bcf629bf8..3107be09a 100644
--- a/sources/pyside6/tests/pysidetest/testobject.cpp
+++ b/sources/pyside6/tests/pysidetest/testobject.cpp
@@ -47,6 +47,11 @@ void TestObject::emitFlagsSignal(Qt::Alignment alignment)
emit flagsSignal(alignment);
}
+void TestObject::emitObjectByConstRef()
+{
+ emit objectByConstRef(*this);
+}
+
void TestObject::setQLatin1String(QLatin1String v)
{
m_qLatin1String = v;
diff --git a/sources/pyside6/tests/pysidetest/testobject.h b/sources/pyside6/tests/pysidetest/testobject.h
index 9689589ad..7c273c891 100644
--- a/sources/pyside6/tests/pysidetest/testobject.h
+++ b/sources/pyside6/tests/pysidetest/testobject.h
@@ -54,6 +54,8 @@ public:
void emitFlagsSignal(Qt::Alignment alignment);
+ void emitObjectByConstRef();
+
static constexpr auto LATIN1_TEST_FIELD = QLatin1StringView("test");
void setQLatin1String(QLatin1String v);
@@ -69,6 +71,7 @@ signals:
void signalWithTypedefValue(TypedefValue value);
void signalWithContainerTypedefValue(const IntList &il);
void flagsSignal(Qt::Alignment alignment);
+ void objectByConstRef(const QObject &qobject);
private:
int m_idValue;