diff options
Diffstat (limited to 'sources/shiboken6/generator/shiboken/cppgenerator_container.cpp')
-rw-r--r-- | sources/shiboken6/generator/shiboken/cppgenerator_container.cpp | 77 |
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"; |