aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken6/generator/shiboken/cppgenerator_container.cpp')
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator_container.cpp77
1 files changed, 49 insertions, 28 deletions
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp b/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp
index 360ae703d..00e0cabea 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp
+++ b/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp
@@ -2,11 +2,13 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "cppgenerator.h"
+#include "generatorstrings.h"
#include <abstractmetalang.h>
#include "apiextractorresult.h"
#include "ctypenames.h"
#include "containertypeentry.h"
#include "textstream.h"
+#include "typedatabase.h"
#include <QtCore/QDebug>
@@ -53,23 +55,37 @@ static void writeSlot(TextStream &s, const QString &privateObjType,
// Write creation function from C++ reference, used by field accessors
// and getters which are within extern "C"
+
+enum ContainerCreationFlag
+{
+ None = 0,
+ Const = 0x1,
+ Allocate = 0x2
+};
+
+Q_DECLARE_FLAGS(ContainerCreationFlags, ContainerCreationFlag)
+Q_DECLARE_OPERATORS_FOR_FLAGS(ContainerCreationFlags)
+
static void writeContainerCreationFunc(TextStream &s,
const QString &funcName,
const QString &typeFName,
const QString &containerSignature,
- bool isConst = false)
+ ContainerCreationFlags flags = {})
{
// creation function from C++ reference, used by field accessors
// which are within extern "C"
s << "extern \"C\" PyObject *" << funcName << '(';
- if (isConst)
+ if (flags.testFlag(ContainerCreationFlag::Const))
s << "const ";
s << containerSignature << "* ct)\n{\n" << indent
<< "auto *container = PyObject_New(ShibokenContainer, " << typeFName << "());\n"
<< "auto *d = new ShibokenSequenceContainerPrivate<"
<< containerSignature << ">();\n";
- if (isConst) {
+ if (flags.testFlag(ContainerCreationFlag::Allocate)) {
+ s << "d->m_list = new " << containerSignature << "(*ct);\n"
+ << "d->m_ownsList = true;\n";
+ } else if (flags.testFlag(ContainerCreationFlag::Const)) {
s << "d->m_list = const_cast<" << containerSignature << " *>(ct);\n"
<< "d->m_const = true;\n";
} else {
@@ -85,20 +101,17 @@ void CppGenerator::writeOpaqueContainerValueConverter(TextStream &s,
const AbstractMetaType &valueType) const
{
// Generate template specialization of value converter helper unless it is already there
- const QString pyArg = u"pyArg"_s;
- const QString cppArg = u"cppArg"_s;
-
const QString valueTypeName = valueType.cppSignature();
const QString checkFunction = cpythonCheckFunction(valueType);
s << "template <>\nstruct ShibokenContainerValueConverter<"
<< valueTypeName << ">\n{\n";
// Type check
- s << indent << "static bool checkValue(PyObject *" << pyArg << ")\n{\n"
+ s << indent << "static bool checkValue(PyObject *" << PYTHON_ARG << ")\n{\n"
<< indent << "return " << checkFunction;
if (!checkFunction.contains(u'('))
s << '(';
- s << pyArg << ");\n"
+ s << PYTHON_ARG << ");\n"
<< outdent << "}\n\n";
// C++ to Python
@@ -110,21 +123,21 @@ void CppGenerator::writeOpaqueContainerValueConverter(TextStream &s,
s << valueTypeName << ' ';
if (passByConstRef)
s << '&';
- s << cppArg << ")\n{\n" << indent << "return ";
- writeToPythonConversion(s, valueType, nullptr, cppArg);
+ s << CPP_ARG << ")\n{\n" << indent << "return ";
+ writeToPythonConversion(s, valueType, nullptr, CPP_ARG);
s << ";\n" << outdent << "}\n\n";
// Python to C++
s << "static std::optional<" << valueTypeName << "> convertValueToCpp(PyObject *"
- << pyArg << ")\n{\n" << indent;
+ << PYTHON_ARG << ")\n{\n" << indent;
s << PYTHON_TO_CPPCONVERSION_STRUCT << ' ' << PYTHON_TO_CPP_VAR << ";\n"
<< "if (!(";
- writeTypeCheck(s, valueType, pyArg), isNumber(valueType.typeEntry());
+ writeTypeCheck(s, valueType, PYTHON_ARG), isNumber(valueType.typeEntry());
s << ")) {\n" << indent
<< "Shiboken::Errors::setWrongContainerType();\n"
<< "return {};\n" << outdent << "}\n";
- writePythonToCppTypeConversion(s, valueType, pyArg, cppArg, nullptr, {});
- s << "return " << cppArg << ";\n" << outdent << "}\n" << outdent << "};\n\n";
+ writePythonToCppTypeConversion(s, valueType, PYTHON_ARG, CPP_ARG, nullptr, {});
+ s << "return " << CPP_ARG << ";\n" << outdent << "}\n" << outdent << "};\n\n";
}
// Generate code for a type wrapping a C++ container instantiation
@@ -153,7 +166,8 @@ CppGenerator::OpaqueContainerData
// methods
const QString &containerName = containerType.name();
const bool isStdVector = containerName == u"std::vector";
- const bool isFixed = containerName == u"std::array";
+ const auto kind = containerTypeEntry->containerKind();
+ const bool isFixed = kind == ContainerTypeEntry::SpanContainer || containerName == u"std::array";
const QString methods = result.name + u"_methods"_s;
s << "static PyMethodDef " << methods << "[] = {\n" << indent;
if (!isFixed) {
@@ -180,7 +194,8 @@ CppGenerator::OpaqueContainerData
const QString slotsList = result.name + u"_slots"_s;
s << "static PyType_Slot " << slotsList << "[] = {\n" << indent;
writeSlot(s, privateObjType, "Py_tp_init", "tpInit");
- writeSlot(s, privateObjType, "Py_tp_new", "tpNew");
+ const auto *tpNew = containerTypeEntry->viewOn() == nullptr ? "tpNew" : "tpNewInvalid";
+ writeSlot(s, privateObjType, "Py_tp_new", tpNew);
writeSlot(s, privateObjType, "Py_tp_free", "tpFree");
writeSlot(s, "Py_tp_dealloc", "Sbk_object_dealloc"); // FIXME?
writeSlot(s, "Py_tp_methods", methods.toUtf8().constData());
@@ -191,7 +206,8 @@ CppGenerator::OpaqueContainerData
// spec
const QString specName = result.name + u"_spec"_s;
- const QString name = moduleName() + u'.' + result.name;
+ const QString name = TypeDatabase::instance()->defaultPackageName()
+ + u'.' + result.name;
s << "static PyType_Spec " << specName << " = {\n" << indent
<< "\"" << name.count(u'.') << ':' << name << "\",\n"
<< "sizeof(ShibokenContainer),\n0,\nPy_TPFLAGS_DEFAULT,\n"
@@ -202,7 +218,8 @@ CppGenerator::OpaqueContainerData
s << "static inline PyTypeObject *" << typeCreationFName << "()\n{\n" << indent
<< "auto *result = reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&"
<< specName << "));\nPy_INCREF(Py_True);\n"
- << "PyDict_SetItem(result->tp_dict, "
+ << "Shiboken::AutoDecRef tpDict(PepType_GetDict(result));\n"
+ << "PyDict_SetItem(tpDict.object(), "
"Shiboken::PyMagicName::opaque_container(), Py_True);\n"
<< "return result;\n" << outdent << "}\n\n";
@@ -213,33 +230,37 @@ CppGenerator::OpaqueContainerData
<< "();\nreturn type;\n" << outdent << "}\n\n";
// creation functions from C++ references
+ ContainerCreationFlags flags;
+ if (kind == ContainerTypeEntry::SpanContainer)
+ flags.setFlag(ContainerCreationFlag::Allocate);
+
writeContainerCreationFunc(s, u"create"_s + result.name, typeFName,
- containerType.cppSignature());
+ containerType.cppSignature(), flags);
+ flags.setFlag(ContainerCreationFlag::Const);
writeContainerCreationFunc(s, u"createConst"_s + result.name, typeFName,
- containerType.cppSignature(), true);
+ containerType.cppSignature(), flags);
// Check function
result.checkFunctionName = result.name + u"_Check"_s;
- const QString pyArg = u"pyArg"_s;
- s << "extern \"C\" int " << result.checkFunctionName << "(PyObject *" << pyArg
- << ")\n{\n" << indent << "return " << pyArg << " != nullptr && "
- << pyArg << " != Py_None && " << pyArg << "->ob_type == "
+ s << "extern \"C\" int " << result.checkFunctionName << "(PyObject *" << PYTHON_ARG
+ << ")\n{\n" << indent << "return " << PYTHON_ARG << " != nullptr && "
+ << PYTHON_ARG << " != Py_None && " << PYTHON_ARG << "->ob_type == "
<< typeFName << "();\n" << outdent << "}\n\n";
// SBK converter Python to C++
result.pythonToConverterFunctionName = u"PythonToCpp"_s + result.name;
s << "extern \"C\" void " << result.pythonToConverterFunctionName
- << "(PyObject *" << pyArg << ", void *cppOut)\n{\n" << indent
+ << "(PyObject *" << PYTHON_ARG << ", void *cppOut)\n{\n" << indent
<< "auto *d = ShibokenSequenceContainerPrivate<" << cppSignature
- << ">::get(" << pyArg << ");\n"
+ << ">::get(" << PYTHON_ARG << ");\n"
<< "*reinterpret_cast<" << cppSignature << "**>(cppOut) = d->m_list;\n"
<< outdent << "}\n\n";
// SBK check function for converting Python to C++ that returns the converter
result.converterCheckFunctionName = u"is"_s + result.name + u"PythonToCppConvertible"_s;
s << "extern \"C\" PythonToCppFunc " << result.converterCheckFunctionName
- << "(PyObject *" << pyArg << ")\n{\n" << indent << "if ("
- << result.checkFunctionName << '(' << pyArg << "))\n" << indent
+ << "(PyObject *" << PYTHON_ARG << ")\n{\n" << indent << "if ("
+ << result.checkFunctionName << '(' << PYTHON_ARG << "))\n" << indent
<< "return " << result.pythonToConverterFunctionName << ";\n"
<< outdent << "return {};\n" << outdent << "}\n\n";