diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2022-05-17 20:31:52 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2022-05-18 13:15:10 +0000 |
commit | 06dd32d94cfc452b2d199d525455af6397f77f3a (patch) | |
tree | a87bd84b3c9361b39bd92de664c8bb0788a57044 | |
parent | ba04130a9ece05644f35ebda12d319e86d71d020 (diff) |
shiboken6: Introduce a struct for PyMethodDef
Instead of passing a maximum number of entries to write,
add a data structure for PyMethodDef and pass lists of it.
Task-number: PYSIDE-1202
Task-number: PYSIDE-1905
Change-Id: I110413aaedaf959aeac2c87f8fe0334f940a793d
Reviewed-by: Christian Tismer <tismer@stackless.com>
(cherry picked from commit ac9619647cf3cb94d57fac4daf955ad541beacb4)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | sources/shiboken6/ApiExtractor/CMakeLists.txt | 1 | ||||
-rw-r--r-- | sources/shiboken6/ApiExtractor/pymethoddefentry.cpp | 66 | ||||
-rw-r--r-- | sources/shiboken6/ApiExtractor/pymethoddefentry.h | 53 | ||||
-rw-r--r-- | sources/shiboken6/generator/shiboken/cppgenerator.cpp | 74 | ||||
-rw-r--r-- | sources/shiboken6/generator/shiboken/cppgenerator.h | 10 |
5 files changed, 152 insertions, 52 deletions
diff --git a/sources/shiboken6/ApiExtractor/CMakeLists.txt b/sources/shiboken6/ApiExtractor/CMakeLists.txt index db3916982..83f55360f 100644 --- a/sources/shiboken6/ApiExtractor/CMakeLists.txt +++ b/sources/shiboken6/ApiExtractor/CMakeLists.txt @@ -27,6 +27,7 @@ messages.cpp modifications.cpp predefined_templates.cpp propertyspec.cpp +pymethoddefentry.cpp reporthandler.cpp sourcelocation.cpp typeparser.cpp diff --git a/sources/shiboken6/ApiExtractor/pymethoddefentry.cpp b/sources/shiboken6/ApiExtractor/pymethoddefentry.cpp new file mode 100644 index 000000000..770a8291a --- /dev/null +++ b/sources/shiboken6/ApiExtractor/pymethoddefentry.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt for Python. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "pymethoddefentry.h" +#include "textstream.h" + +#include <QtCore/QDebug> + +TextStream &operator<<(TextStream &s, const PyMethodDefEntry &e) +{ + s << "{\"" << e.name << "\", reinterpret_cast<PyCFunction>(" + << e.function << "), "; + if (e.methFlags.isEmpty()) { + s << '0'; + } else { + for (qsizetype i = 0, size = e.methFlags.size(); i < size; ++i) { + if (i) + s << '|'; + s << e.methFlags.at(i); + } + } + s << '}'; + return s; +} + +TextStream &operator<<(TextStream &s, const PyMethodDefEntries &entries) +{ + for (const auto &e : entries) + s << e << ",\n"; + return s; +} + +QDebug operator<<(QDebug debug, const PyMethodDefEntry &e) +{ + QDebugStateSaver saver(debug); + debug.noquote(); + debug.nospace(); + debug << "PyMethodDefEntry(\"" << e.name << "\", " << e.function + << ", " << e.methFlags << ')'; + return debug; +} diff --git a/sources/shiboken6/ApiExtractor/pymethoddefentry.h b/sources/shiboken6/ApiExtractor/pymethoddefentry.h new file mode 100644 index 000000000..1a0a0e0af --- /dev/null +++ b/sources/shiboken6/ApiExtractor/pymethoddefentry.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt for Python. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PYMETHODDEFENTRY_H +#define PYMETHODDEFENTRY_H + +#include <QtCore/QByteArrayList> +#include <QtCore/QString> + +QT_FORWARD_DECLARE_CLASS(QDebug) + +class TextStream; + +struct PyMethodDefEntry +{ + QString name; + QString function; + QByteArrayList methFlags; // "METH_O" etc. +}; + +using PyMethodDefEntries = QList<PyMethodDefEntry>; + +TextStream &operator<<(TextStream &s, const PyMethodDefEntry &e); +TextStream &operator<<(TextStream &s, const PyMethodDefEntries &e); + +QDebug operator<<(QDebug debug, const PyMethodDefEntry &e); + +#endif // PYMETHODDEFENTRY_H diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp index 3f1c72988..64d99ef74 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp @@ -35,6 +35,7 @@ #include "pytypenames.h" #include "fileout.h" #include "overloaddata.h" +#include "pymethoddefentry.h" #include <abstractmetaenum.h> #include <abstractmetafield.h> #include <abstractmetafunction.h> @@ -631,13 +632,14 @@ void CppGenerator::generateClass(TextStream &s, const GeneratorContext &classCon // a separate PyMethodDef entry is written which is referenced // in the PyMethodDef list and later in getattro() for handling // the non-static case. + const auto defEntries = methodDefinitionEntries(overloadData); if (OverloadData::hasStaticAndInstanceFunctions(overloads)) { QString methDefName = cpythonMethodDefinitionName(rfunc); - smd << "static PyMethodDef " << methDefName << " = " << indent; - writeMethodDefinitionEntries(smd, overloadData, 1); - smd << outdent << ";\n\n"; + smd << "static PyMethodDef " << methDefName << " = " << indent + << defEntries.constFirst() << outdent << ";\n\n"; } - writeMethodDefinition(md, overloadData); + if (!m_tpFuncs.contains(rfunc->name())) + md << defEntries; } } const QString methodsDefinitions = md.toString(); @@ -929,7 +931,7 @@ void CppGenerator::writeMethodWrapper(TextStream &s, TextStream &definitionStrea OverloadData overloadData(overloads, api()); writeMethodWrapper(s, overloadData, classContext); writeSignatureInfo(signatureStream, overloadData); - writeMethodDefinition(definitionStream, overloadData); + definitionStream << methodDefinitionEntries(overloadData); } void CppGenerator::writeCacheResetNative(TextStream &s, const GeneratorContext &classContext) @@ -5277,68 +5279,48 @@ void CppGenerator::writeSmartPointerRichCompareFunction(TextStream &s, writeRichCompareFunctionFooter(s, baseName); } -QString CppGenerator::methodDefinitionParameters(const OverloadData &overloadData) const +// Return a flag combination for PyMethodDef +QByteArrayList CppGenerator::methodDefinitionParameters(const OverloadData &overloadData) const { const bool usePyArgs = overloadData.pythonFunctionWrapperUsesListOfArguments(); - const auto func = overloadData.referenceFunction(); int min = overloadData.minArgs(); int max = overloadData.maxArgs(); - QString result; - QTextStream s(&result); - s << "reinterpret_cast<PyCFunction>(" - << cpythonFunctionName(func) << "), "; + QByteArrayList result; if ((min == max) && (max < 2) && !usePyArgs) { - if (max == 0) - s << "METH_NOARGS"; - else - s << "METH_O"; + result.append(max == 0 ? QByteArrayLiteral("METH_NOARGS") + : QByteArrayLiteral("METH_O")); } else { - s << "METH_VARARGS"; + result.append(QByteArrayLiteral("METH_VARARGS")); if (overloadData.hasArgumentWithDefaultValue()) - s << "|METH_KEYWORDS"; + result.append(QByteArrayLiteral("METH_KEYWORDS")); } // METH_STATIC causes a crash when used for global functions (also from // invisible namespaces). - auto ownerClass = func->ownerClass(); + auto *ownerClass = overloadData.referenceFunction()->ownerClass(); if (ownerClass && !invisibleTopNamespaces().contains(const_cast<AbstractMetaClass *>(ownerClass))) { if (overloadData.hasStaticFunction()) - s << "|METH_STATIC"; + result.append(QByteArrayLiteral("METH_STATIC")); if (overloadData.hasClassMethod()) - s << "|METH_CLASS"; + result.append(QByteArrayLiteral("METH_CLASS")); } return result; } -void CppGenerator::writeMethodDefinitionEntries(TextStream &s, - const OverloadData &overloadData, - qsizetype maxEntries) const +QList<PyMethodDefEntry> + CppGenerator::methodDefinitionEntries(const OverloadData &overloadData) const { - const QStringList names = overloadData.referenceFunction()->definitionNames(); - const QString parameters = methodDefinitionParameters(overloadData); - const qsizetype count = maxEntries > 0 - ? qMin(names.size(), maxEntries) : names.size(); - for (qsizetype i = 0; i < count; ++i) { - if (i) - s << ",\n"; - s << "{\"" << names.at(i) << "\", " << parameters << '}'; - } -} -void CppGenerator::writeMethodDefinition(TextStream &s, - const OverloadData &overloadData) const -{ - const auto func = overloadData.referenceFunction(); - if (m_tpFuncs.contains(func->name())) - return; + const QStringList names = overloadData.referenceFunction()->definitionNames(); + const QString funcName = cpythonFunctionName(overloadData.referenceFunction()); + const QByteArrayList parameters = methodDefinitionParameters(overloadData); - if (OverloadData::hasStaticAndInstanceFunctions(overloadData.overloads())) { - s << cpythonMethodDefinitionName(func); - } else { - writeMethodDefinitionEntries(s, overloadData); - } - s << ',' << '\n'; + QList<PyMethodDefEntry> result; + result.reserve(names.size()); + for (const auto &name : names) + result.append({name, funcName, parameters}); + return result; } // Format the type signature of a function parameter @@ -6391,7 +6373,7 @@ bool CppGenerator::finishGeneration() writeMethodWrapper(s_globalFunctionImpl, overloadData, classContext); writeSignatureInfo(signatureStream, overloadData); - writeMethodDefinition(s_globalFunctionDef, overloadData); + s_globalFunctionDef << methodDefinitionEntries(overloadData); } AbstractMetaClassCList classesWithStaticFields; diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.h b/sources/shiboken6/generator/shiboken/cppgenerator.h index 6b1df070a..92b712dc3 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.h +++ b/sources/shiboken6/generator/shiboken/cppgenerator.h @@ -37,6 +37,7 @@ class OverloadDataNode; class OverloadDataRootNode; +struct PyMethodDefEntry; /** * The CppGenerator generate the implementations of C++ bindings classes. @@ -380,12 +381,9 @@ private: void writeClassDefinition(TextStream &s, const AbstractMetaClass *metaClass, const GeneratorContext &classContext); - QString methodDefinitionParameters(const OverloadData &overloadData) const; - void writeMethodDefinitionEntries(TextStream &s, - const OverloadData &overloadData, - qsizetype maxEntries = -1) const; - void writeMethodDefinition(TextStream &s, - const OverloadData &overloadData) const; + QByteArrayList methodDefinitionParameters(const OverloadData &overloadData) const; + QList<PyMethodDefEntry> methodDefinitionEntries(const OverloadData &overloadData) const; + void writeSignatureInfo(TextStream &s, const OverloadData &overloads) const; QString signatureParameter(const AbstractMetaArgument &arg) const; /// Writes the implementation of all methods part of python sequence protocol |