From 6c8c0142a99aa0c170998b3449ea20e5a526d80d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 23 Nov 2021 13:44:23 +0100 Subject: shiboken6: Handle None as a shared pointer parameter Add checks for None to the copy converters. Pick-to: 6.2 Task-number: PYSIDE-454 Change-Id: I03954189e26572d248e22118954115bf8281b0f9 Reviewed-by: Qt CI Bot Reviewed-by: Christian Tismer --- .../shiboken6/generator/shiboken/cppgenerator.cpp | 29 ++++++++++++++++------ sources/shiboken6/tests/libsmart/smart.cpp | 14 +++++++++++ sources/shiboken6/tests/libsmart/smart_obj.h | 1 + .../tests/smartbinding/smart_pointer_test.py | 8 ++++++ 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp index 7a22c83f2..386254ce8 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp @@ -1569,18 +1569,31 @@ return result;)"; c.clear(); QString pyInVariable = QLatin1String("pyIn"); - QString wrappedCPtrExpression; - if (!classContext.forSmartPointer()) - wrappedCPtrExpression = cpythonWrapperCPtr(metaClass->typeEntry(), pyInVariable); - else - wrappedCPtrExpression = cpythonWrapperCPtr(classContext.preciseType(), pyInVariable); + const QString outPtr = u"reinterpret_cast<"_qs + typeName + u" *>(cppOut)"_qs; + if (!classContext.forSmartPointer()) { + c << '*' << outPtr << " = *" + << cpythonWrapperCPtr(metaClass->typeEntry(), pyInVariable) << ';'; + } else { + auto *ste = static_cast(metaClass->typeEntry()); + const QString resetMethod = ste->resetMethod(); + c << "auto *ptr = " << outPtr << ";\n"; + c << "if (" << pyInVariable << " == Py_None)\n" << indent; + if (resetMethod.isEmpty()) + c << "*ptr = {};\n"; + else + c << "ptr->" << resetMethod << "();\n"; + c << outdent << "else\n" << indent + << "*ptr = *" + << cpythonWrapperCPtr(classContext.preciseType(), pyInVariable) << ';'; + } - c << "*reinterpret_cast<" << typeName << " *>(cppOut) = *" - << wrappedCPtrExpression << ';'; writePythonToCppFunction(s, c.toString(), sourceTypeName, targetTypeName); // "Is convertible" function for the Python object to C++ value copy conversion. - writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, pyTypeCheck); + QString copyTypeCheck = pyTypeCheck; + if (classContext.forSmartPointer()) + copyTypeCheck.prepend(pyInVariable + u" == Py_None || "_qs); + writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, copyTypeCheck); s << '\n'; // User provided implicit conversions. diff --git a/sources/shiboken6/tests/libsmart/smart.cpp b/sources/shiboken6/tests/libsmart/smart.cpp index 6908c7881..3a1c36977 100644 --- a/sources/shiboken6/tests/libsmart/smart.cpp +++ b/sources/shiboken6/tests/libsmart/smart.cpp @@ -133,6 +133,20 @@ int Obj::takeSharedPtrToObj(SharedPtr pObj) int Obj::takeSharedPtrToInteger(SharedPtr pInt) { + if (pInt.isNull()) { + std::cout << "SharedPtr(nullptr) passed!\n"; + return -1; + } + pInt->printInteger(); + return pInt->value(); +} + +int Obj::takeSharedPtrToIntegerByConstRef(const SharedPtr &pInt) +{ + if (pInt.isNull()) { + std::cout << "SharedPtr(nullptr) passed!\n"; + return -1; + } pInt->printInteger(); return pInt->value(); } diff --git a/sources/shiboken6/tests/libsmart/smart_obj.h b/sources/shiboken6/tests/libsmart/smart_obj.h index 9cd8e5f08..2adc30cbb 100644 --- a/sources/shiboken6/tests/libsmart/smart_obj.h +++ b/sources/shiboken6/tests/libsmart/smart_obj.h @@ -54,6 +54,7 @@ public: SharedPtr giveSharedPtrToInteger2(); int takeSharedPtrToObj(SharedPtr pObj); int takeSharedPtrToInteger(SharedPtr pInt); + int takeSharedPtrToIntegerByConstRef(const SharedPtr &pInt); static SharedPtr createSharedPtrToInteger(int value); static SharedPtr createNullSharedPtrToInteger(); diff --git a/sources/shiboken6/tests/smartbinding/smart_pointer_test.py b/sources/shiboken6/tests/smartbinding/smart_pointer_test.py index 3cafb74b9..b1e50fffd 100644 --- a/sources/shiboken6/tests/smartbinding/smart_pointer_test.py +++ b/sources/shiboken6/tests/smartbinding/smart_pointer_test.py @@ -278,6 +278,14 @@ class SmartPointerTests(unittest.TestCase): zero = Obj.createSharedPtrToInteger(0) self.assertTrue(zero) + def testParameterNone(self): + o = Obj() + null_ptr = Obj.createNullSharedPtrToInteger() + o.takeSharedPtrToInteger(null_ptr) + o.takeSharedPtrToIntegerByConstRef(null_ptr) + o.takeSharedPtrToInteger(None) + o.takeSharedPtrToIntegerByConstRef(None) + if __name__ == '__main__': unittest.main() -- cgit v1.2.3