From 24cd62c9d18850707574ba7eb637ff24bee353a1 Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Tue, 6 Oct 2020 09:49:18 -0300 Subject: 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 as argument should be able to accept SharedPointer if B is derived from A. Task-number: PYSIDE-1397 Change-Id: I7e5235980daaf4651dad3ab1c880373f1c64e134 Reviewed-by: Friedemann Kleint --- .../shiboken2/generator/shiboken2/cppgenerator.cpp | 97 +++++++++++++++++++++- 1 file changed, 94 insertions(+), 3 deletions(-) (limited to 'sources/shiboken2/generator/shiboken2/cppgenerator.cpp') 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; // 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( + 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& 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) { -- cgit v1.2.3