aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/generator/shiboken/cppgenerator.cpp
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2021-07-14 14:15:02 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2021-09-24 13:52:35 +0200
commitbce1bfb3af99aeb24259df34d662e8fcf072d3fd (patch)
treeef36333a2b059f4278cc5aad4efa860f9e4cd30b /sources/shiboken6/generator/shiboken/cppgenerator.cpp
parent79b32f4d4b5154ba8001bafc481fb6edacc10280 (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.cpp66
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) {