diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2021-07-14 14:15:02 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2021-09-24 13:52:35 +0200 |
commit | bce1bfb3af99aeb24259df34d662e8fcf072d3fd (patch) | |
tree | ef36333a2b059f4278cc5aad4efa860f9e4cd30b /sources/shiboken6/generator/shiboken/cppgenerator.cpp | |
parent | 79b32f4d4b5154ba8001bafc481fb6edacc10280 (diff) |
shiboken6: Add opaque containers for C++ sequence containers
Add a class that directly wraps a C++ sequence container,
allow for modifying them.
For all instantiated containers, generate a special (sequence) type
that wraps the C++ container directly. For example, it will be
accessible as a QList_int.
This is achieved via providing a template for a type private
that relies on a conversion traits template for conversion.
Only the conversion traits specialization code needs to be generated.
Use cases:
- Allowing for modifying Fields of such container types
(non-owning)
- Pass it into functions taking such containers instead of converting
back and forth from a PyList (constructed in Python, owning)
[ChangeLog][shiboken6] Support for opaque C++ sequence scontainers
has been added, allowing to pass a wrapped C++ container
directly instead of converting it back and forth from
Python sequences.
Task-number: PYSIDE-1605
Change-Id: I49d378eb1a0151730d817d5bdd4b71a7c3b5cdda
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
Diffstat (limited to 'sources/shiboken6/generator/shiboken/cppgenerator.cpp')
-rw-r--r-- | sources/shiboken6/generator/shiboken/cppgenerator.cpp | 66 |
1 files changed, 57 insertions, 9 deletions
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp index e7648f736..8e1a2c934 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp @@ -1218,7 +1218,8 @@ void CppGenerator::writeVirtualMethodNative(TextStream &s, writeConversionRule(s, func, TypeSystem::NativeCode, QLatin1String(CPP_RETURN_VAR)); } else if (!func->injectedCodeHasReturnValueAttribution(TypeSystem::NativeCode)) { writePythonToCppTypeConversion(s, func->type(), QLatin1String(PYTHON_RETURN_VAR), - QLatin1String(CPP_RETURN_VAR), func->implementingClass()); + QLatin1String(CPP_RETURN_VAR), func->implementingClass(), {}, + PythonToCppTypeConversionFlag::DisableOpaqueContainers); } } } @@ -2578,7 +2579,8 @@ void CppGenerator::writePythonToCppTypeConversion(TextStream &s, const QString &pyIn, const QString &cppOut, const AbstractMetaClass *context, - const QString &defaultValue) const + const QString &defaultValue, + PythonToCppTypeConversionFlags flags) const { const TypeEntry *typeEntry = type.typeEntry(); if (typeEntry->isCustom() || typeEntry->isVarargs()) @@ -2590,6 +2592,9 @@ void CppGenerator::writePythonToCppTypeConversion(TextStream &s, const bool isEnum = typeEntry->isEnum(); const bool isFlags = typeEntry->isFlags(); const bool treatAsPointer = type.valueTypeWithCopyConstructorOnlyPassed(); + const bool maybeOpaqueContainer = + !flags.testFlag(PythonToCppTypeConversionFlag::DisableOpaqueContainers) + && type.generateOpaqueContainer(); bool isPointerOrObjectType = (type.isObjectType() || type.isPointer()) && !type.isUserPrimitive() && !type.isExtendedCppPrimitive() && !isEnum && !isFlags; @@ -2603,8 +2608,9 @@ void CppGenerator::writePythonToCppTypeConversion(TextStream &s, // For implicit conversions or containers, either value or pointer conversion // may occur. An implicit conversion uses value conversion whereas the object - // itself uses pointer conversion. - const bool valueOrPointer = mayHaveImplicitConversion; + // itself uses pointer conversion. For containers, the PyList/container + // conversion is by value whereas opaque containers use pointer conversion. + const bool valueOrPointer = mayHaveImplicitConversion || maybeOpaqueContainer; const AbstractMetaTypeList &nestedArrayTypes = type.nestedArrayTypes(); const bool isCppPrimitiveArray = !nestedArrayTypes.isEmpty() @@ -2665,7 +2671,7 @@ void CppGenerator::writePythonToCppTypeConversion(TextStream &s, QString pythonToCppCall = pythonToCppFunc + u'(' + pyIn + u", &"_qs + cppOut + u')'; - if (!mayHaveImplicitConversion) { + if (!valueOrPointer) { // pythonToCppFunc may be 0 when less parameters are passed and // the defaultValue takes effect. if (!defaultValue.isEmpty()) @@ -3306,7 +3312,8 @@ void CppGenerator::writePythonToCppConversionFunctions(TextStream &s, const Abst for (int i = 0; i < containerType.instantiations().count(); ++i) { const AbstractMetaType &type = containerType.instantiations().at(i); QString typeName = getFullTypeName(type); - if (type.shouldDereferenceArgument()) { + // Containers of opaque containers are not handled here. + if (type.shouldDereferenceArgument() && !type.generateOpaqueContainer()) { for (int pos = 0; ; ) { const QRegularExpressionMatch match = convertToCppRegEx().match(code, pos); if (!match.hasMatch()) @@ -4126,7 +4133,7 @@ void CppGenerator::writeEnumConverterInitialization(TextStream &s, const TypeEnt writeEnumConverterInitialization(s, static_cast<const EnumTypeEntry *>(enumType)->flags()); } -void CppGenerator::writeContainerConverterInitialization(TextStream &s, const AbstractMetaType &type) const +QString CppGenerator::writeContainerConverterInitialization(TextStream &s, const AbstractMetaType &type) const { QByteArray cppSignature = QMetaObject::normalizedSignature(type.cppSignature().toUtf8()); s << "// Register converter for type '" << cppSignature << "'.\n"; @@ -4150,7 +4157,9 @@ void CppGenerator::writeContainerConverterInitialization(TextStream &s, const Ab cppSignature.remove(0, sizeof("const ") / sizeof(char) - 1); s << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << cppSignature << "\");\n"; } - writeAddPythonToCppConversion(s, converterObject(type), toCpp, isConv); + const QString converterObj = converterObject(type); + writeAddPythonToCppConversion(s, converterObj, toCpp, isConv); + return converterObj; } void CppGenerator::writeSmartPointerConverterInitialization(TextStream &s, const AbstractMetaType &type) const @@ -4723,6 +4732,22 @@ void CppGenerator::writeGetterFunction(TextStream &s, && !fieldType.isPointer(); QString cppField = cppFieldAccess(metaField, context); + + if (metaField.generateOpaqueContainer() + && fieldType.generateOpaqueContainer()) { + const auto *containerTypeEntry = + static_cast<const ContainerTypeEntry *>(fieldType.typeEntry()); + const auto *instantiationTypeEntry = + fieldType.instantiations().constFirst().typeEntry(); + const QString creationFunc = + u"create"_qs + containerTypeEntry->opaqueContainerName(instantiationTypeEntry->name()); + s << "PyObject *" << creationFunc << '(' << fieldType.cppSignature() << "*);\n" + << "PyObject *pyOut = " << creationFunc + << "(&" << cppField << ");\nPy_IncRef(pyOut);\n" + << "return pyOut;\n" << outdent << "}\n"; + return; + } + if (newWrapperSameObject) { cppField.prepend(u"&("); cppField.append(u')'); @@ -6143,6 +6168,10 @@ bool CppGenerator::finishGeneration() #include <algorithm> #include <signature.h> )"; + + if (!instantiatedContainers().isEmpty()) + s << "#include <sbkcontainer.h>\n#include <sbkstaticstrings.h>\n"; + if (usePySideExtensions()) { s << includeQDebug; s << R"(#include <pyside.h> @@ -6269,12 +6298,17 @@ bool CppGenerator::finishGeneration() s << '\n'; } + QHash<AbstractMetaType, OpaqueContainerData> opaqueContainers; const auto &containers = instantiatedContainers(); if (!containers.isEmpty()) { s << "// Container Type converters.\n\n"; for (const AbstractMetaType &container : containers) { s << "// C++ to Python conversion for container type '" << container.cppSignature() << "'.\n"; writeContainerConverterFunctions(s, container); + if (container.generateOpaqueContainer()) { + opaqueContainers.insert(container, + writeOpaqueContainerConverterFunctions(s, container)); + } } s << '\n'; } @@ -6358,11 +6392,25 @@ bool CppGenerator::finishGeneration() if (!containers.isEmpty()) { s << '\n'; for (const AbstractMetaType &container : containers) { - writeContainerConverterInitialization(s, container); + const QString converterObj = writeContainerConverterInitialization(s, container); + const auto it = opaqueContainers.constFind(container); + if (it != opaqueContainers.constEnd()) { + writeSetPythonToCppPointerConversion(s, converterObj, + it.value().pythonToConverterFunctionName, + it.value().converterCheckFunctionName); + } s << '\n'; } } + if (!opaqueContainers.isEmpty()) { + s << "\n// Opaque container type registration\n" + << "PyObject *ob_type{};\n"; + for (const auto &d : opaqueContainers) + s << d.registrationCode; + s << '\n'; + } + if (!smartPointersList.isEmpty()) { s << '\n'; for (const AbstractMetaType &smartPointer : smartPointersList) { |