aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
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 /sources/shiboken2/generator/shiboken2/cppgenerator.cpp
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>
Diffstat (limited to 'sources/shiboken2/generator/shiboken2/cppgenerator.cpp')
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp97
1 files changed, 94 insertions, 3 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) {