aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRenato Araujo Oliveira Filho <renato.araujo@kdab.com>2020-10-06 09:49:18 -0300
committerRenato Araujo Oliveira Filho <renato.araujo@kdab.com>2020-10-21 16:26:39 -0300
commit24cd62c9d18850707574ba7eb637ff24bee353a1 (patch)
treeb0b7a84f6e9dc422bfbf973138f9cade773416c5
parent85bb24c39df53ea61f59351a60f4284c32cb50ff (diff)
Update SmartPointers conversions
* Updated test to accept base types derived using std::shared_ptr; * Generate new coode to be able to convert smart pointers into shared pointers of base class. Functions that accepts SharedPointer<A> as argument should be able to accept SharedPointer<B> if B is derived from A. Task-number: PYSIDE-1397 Change-Id: I7e5235980daaf4651dad3ab1c880373f1c64e134 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp97
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.h5
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.cpp2
-rw-r--r--sources/shiboken2/tests/smartbinding/smart_pointer_test.py13
4 files changed, 113 insertions, 4 deletions
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
index fe98146e3..05d9d97d6 100644
--- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
@@ -255,6 +255,15 @@ const AbstractMetaFunction *CppGenerator::boolCast(const AbstractMetaClass *meta
&& func->arguments().isEmpty() ? func : nullptr;
}
+const AbstractMetaType *CppGenerator::findSmartPointerInstantiation(const TypeEntry *entry) const
+{
+ for (auto i : instantiatedSmartPointers()) {
+ if (i->instantiations().at(0)->typeEntry() == entry)
+ return i;
+ }
+ return nullptr;
+}
+
using FunctionGroupMap = QMap<QString, AbstractMetaFunctionList>;
// Prevent ELF symbol qt_version_tag from being generated into the source
@@ -1644,6 +1653,7 @@ void CppGenerator::writeConverterRegister(QTextStream &s, const AbstractMetaClas
}
};
+
if (!classContext.forSmartPointer()) {
writeConversionsForType(metaClass->qualifiedCppName());
} else {
@@ -1654,7 +1664,7 @@ void CppGenerator::writeConverterRegister(QTextStream &s, const AbstractMetaClas
Qt::SkipEmptyParts);
while (!lst.isEmpty()) {
QString signature = lst.join(QLatin1String("::"));
- writeConversions(QStringLiteral("%1<%2>").arg(smartPointerName, signature));
+ writeConversions(QStringLiteral("%1<%2 >").arg(smartPointerName, signature));
lst.removeFirst();
}
@@ -1746,6 +1756,30 @@ void CppGenerator::writeContainerConverterFunctions(QTextStream &s, const Abstra
writePythonToCppConversionFunctions(s, containerType);
}
+void CppGenerator::writeSmartPointerConverterFunctions(QTextStream &s, const AbstractMetaType *smartPointerType)
+{
+ const AbstractMetaClass *targetClass = AbstractMetaClass::findClass(classes(), smartPointerType->instantiations().at(0)->typeEntry());
+
+ if (targetClass) {
+ const auto *smartPointerTypeEntry =
+ static_cast<const SmartPointerTypeEntry *>(
+ smartPointerType->typeEntry());
+
+ // TODO: Missing conversion to smart pointer pointer type:
+
+ s << "// Register smartpointer conversion for all derived classes\n";
+ const auto classes = getBaseClasses(targetClass);
+ for (auto k : classes) {
+ if (smartPointerTypeEntry->matchesInstantiation(k->typeEntry())) {
+ if (auto smartTargetType = findSmartPointerInstantiation(k->typeEntry())) {
+ s << INDENT << "// SmartPointer derived class: " << smartTargetType->cppSignature() << "\n";
+ writePythonToCppConversionFunctions(s, smartPointerType, smartTargetType, {}, {}, {});
+ }
+ }
+ }
+ }
+}
+
void CppGenerator::writeMethodWrapperPreamble(QTextStream &s, OverloadData &overloadData,
const GeneratorContext &context)
{
@@ -3062,10 +3096,10 @@ void CppGenerator::writePythonToCppConversionFunctions(QTextStream &s,
QTextStream c(&code);
Indentor nested;
if (conversion.isEmpty())
- conversion = QLatin1Char('*') + cpythonWrapperCPtr(sourceType->typeEntry(), QLatin1String("pyIn"));
+ conversion = QLatin1Char('*') + cpythonWrapperCPtr(sourceType, QLatin1String("pyIn"));
if (!preConversion.isEmpty())
c << nested << preConversion << Qt::endl;
- const QString fullTypeName = getFullTypeName(targetType->typeEntry());
+ const QString fullTypeName = targetType->isSmartPointer() ? targetType->cppSignature() : getFullTypeName(targetType->typeEntry());
c << nested << "*reinterpret_cast<" << fullTypeName << " *>(cppOut) = "
<< fullTypeName << '(' << conversion << ");";
QString sourceTypeName = fixedCppTypeName(sourceType);
@@ -3933,6 +3967,44 @@ void CppGenerator::writeContainerConverterInitialization(QTextStream &s, const A
writeAddPythonToCppConversion(s, converterObject(type), toCpp, isConv);
}
+void CppGenerator::writeSmartPointerConverterInitialization(QTextStream &s, const AbstractMetaType *type)
+{
+ const QByteArray cppSignature = type->cppSignature().toUtf8();
+ auto writeConversionRegister = [this, &s](const AbstractMetaType *sourceType, const QString &targetTypeName, const QString &targetConverter)
+ {
+ const QString sourceTypeName = fixedCppTypeName(sourceType);
+ const QString toCpp = pythonToCppFunctionName(sourceTypeName, targetTypeName);
+ const QString isConv = convertibleToCppFunctionName(sourceTypeName, targetTypeName);
+
+ writeAddPythonToCppConversion(s, targetConverter, toCpp, isConv);
+ };
+
+ auto klass = AbstractMetaClass::findClass(classes(), type->instantiations().at(0)->typeEntry());
+ if (!klass)
+ return;
+
+ const auto classes = getBaseClasses(klass);
+ if (classes.isEmpty())
+ return;
+
+ s << INDENT << "// Register SmartPointer converter for type '" << cppSignature << "'." << Qt::endl;
+ s << INDENT << "///////////////////////////////////////////////////////////////////////////////////////"<< Qt::endl;
+ s << Qt::endl;
+
+ for (auto k : classes) {
+ if (auto smartTargetType = findSmartPointerInstantiation(k->typeEntry()))
+ {
+ s << INDENT << "// Convert to SmartPointer derived class: [" << smartTargetType->cppSignature() << "]" << Qt::endl;
+ const QString converter = QLatin1String("Shiboken::Conversions::getConverter(\"%1\")").arg(smartTargetType->cppSignature());
+ writeConversionRegister(type, fixedCppTypeName(smartTargetType), converter);
+ } else {
+ s << INDENT << "// Class not found:" << type->instantiations().at(0)->cppSignature();
+ }
+ }
+
+ s << INDENT << "///////////////////////////////////////////////////////////////////////////////////////"<< Qt::endl << Qt::endl;
+}
+
void CppGenerator::writeExtendedConverterInitialization(QTextStream &s, const TypeEntry *externalType,
const QVector<const AbstractMetaClass *>& conversions)
{
@@ -6003,6 +6075,17 @@ bool CppGenerator::finishGeneration()
s << Qt::endl;
}
+ // Implicit smart pointers conversions
+ const auto smartPointersList = instantiatedSmartPointers();
+ if (!smartPointersList.isEmpty()) {
+ s << "// SmartPointers converters.\n\n";
+ for (const AbstractMetaType *smartPointer : smartPointersList) {
+ s << "// C++ to Python conversion for type '" << smartPointer->cppSignature() << "'.\n";
+ writeSmartPointerConverterFunctions(s, smartPointer);
+ }
+ s << Qt::endl;
+ }
+
s << "#ifdef IS_PY3K\n";
s << "static struct PyModuleDef moduledef = {\n";
s << " /* m_base */ PyModuleDef_HEAD_INIT,\n";
@@ -6082,6 +6165,14 @@ bool CppGenerator::finishGeneration()
}
}
+ if (!smartPointersList.isEmpty()) {
+ s << Qt::endl;
+ for (const AbstractMetaType *smartPointer : smartPointersList) {
+ writeSmartPointerConverterInitialization(s, smartPointer);
+ s << Qt::endl;
+ }
+ }
+
if (!extendedConverters.isEmpty()) {
s << Qt::endl;
for (ExtendedConverterData::const_iterator it = extendedConverters.cbegin(), end = extendedConverters.cend(); it != end; ++it) {
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.h b/sources/shiboken2/generator/shiboken2/cppgenerator.h
index 1d7894734..41bd17f21 100644
--- a/sources/shiboken2/generator/shiboken2/cppgenerator.h
+++ b/sources/shiboken2/generator/shiboken2/cppgenerator.h
@@ -81,6 +81,8 @@ private:
void writeContainerConverterFunctions(QTextStream &s, const AbstractMetaType *containerType);
+ void writeSmartPointerConverterFunctions(QTextStream &s, const AbstractMetaType *smartPointerType);
+
void writeMethodWrapperPreamble(QTextStream &s, OverloadData &overloadData,
const GeneratorContext &context);
void writeConstructorWrapper(QTextStream &s, const AbstractMetaFunctionList &overloads,
@@ -332,6 +334,7 @@ private:
void writeEnumConverterInitialization(QTextStream &s, const TypeEntry *enumType);
void writeEnumConverterInitialization(QTextStream &s, const AbstractMetaEnum *metaEnum);
void writeContainerConverterInitialization(QTextStream &s, const AbstractMetaType *type);
+ void writeSmartPointerConverterInitialization(QTextStream &s, const AbstractMetaType *type);
void writeExtendedConverterInitialization(QTextStream &s, const TypeEntry *externalType, const QVector<const AbstractMetaClass *>& conversions);
void writeParentChildManagement(QTextStream &s, const AbstractMetaFunction *func, bool userHeuristicForReturn);
@@ -375,6 +378,8 @@ private:
bool hasBoolCast(const AbstractMetaClass *metaClass) const
{ return boolCast(metaClass) != nullptr; }
+ const AbstractMetaType *findSmartPointerInstantiation(const TypeEntry *entry) const;
+
// Number protocol structure members names.
static QHash<QString, QString> m_nbFuncs;
diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
index 4ff3e8408..5d8685b90 100644
--- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
@@ -860,7 +860,7 @@ QString ShibokenGenerator::converterObject(const AbstractMetaType *type)
+ QLatin1String(">(") + QString::number(nestedArrayTypes.size())
+ QLatin1Char(')');
}
- if (type->typeEntry()->isContainer()) {
+ if (type->typeEntry()->isContainer() || type->typeEntry()->isSmartPointer()) {
return convertersVariableName(type->typeEntry()->targetLangPackage())
+ QLatin1Char('[') + getTypeIndexVariableName(type) + QLatin1Char(']');
}
diff --git a/sources/shiboken2/tests/smartbinding/smart_pointer_test.py b/sources/shiboken2/tests/smartbinding/smart_pointer_test.py
index 50b2120a2..d7ddf963c 100644
--- a/sources/shiboken2/tests/smartbinding/smart_pointer_test.py
+++ b/sources/shiboken2/tests/smartbinding/smart_pointer_test.py
@@ -214,6 +214,19 @@ class SmartPointerTests(unittest.TestCase):
except AttributeError as error:
self.assertEqual(error.args[0], "'smart.SharedPtr_Obj' object has no attribute 'typo'")
+ def testSmartPointerConversions(self):
+ # Create Obj.
+ o = Obj()
+ self.assertEqual(objCount(), 1)
+ self.assertEqual(integerCount(), 1)
+
+ # Create a shared pointer to an Integer2
+ integer2 = o.giveSharedPtrToInteger2()
+ self.assertEqual(integer2.value(), 456)
+
+ # pass Smart<Integer2> to a function that accepts Smart<Integer>
+ r = o.takeSharedPtrToInteger(integer2)
+ self.assertEqual(r, integer2.value())
if __name__ == '__main__':
unittest.main()