diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2021-09-13 13:45:54 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2021-09-24 13:52:35 +0200 |
commit | 79b32f4d4b5154ba8001bafc481fb6edacc10280 (patch) | |
tree | 2ebd4470b1eef8e9cd231213901ac6ca2c454f06 | |
parent | d9bad33ad2cd0e49e22c82f8d05422274cbbf1c8 (diff) |
shiboken6: Rewrite conversions
Currently, the isPythonToCpp(Value/Reference/Pointer)Convertible
functions used by the overload decisor return a function pointer. In the case
of isPythonToCppReferenceConvertible, this can be either a pointer
conversion taking a Foo** or a value conversion taking a Foo*.
The function isImplicitConversion(SbkObjectType *, PythonToCppFunc)
is called further down in the generated code to check whether it
is a value or a pointer.
In order to get rid of this, introduce a new version of the
checking function that returns a struct that has the function
and knows its type.
Add an overload of isPythonToCppReferenceConvertible() taking
a SbkConverter for the upcoming opaque containers.
Task-number: PYSIDE-1605
Change-Id: I49f70b85d01500d95208f0f2dd290bf23cb80eff
Reviewed-by: Christian Tismer <tismer@stackless.com>
5 files changed, 98 insertions, 20 deletions
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp index d0dfe7f27..e7648f736 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp @@ -59,6 +59,7 @@ #include <cstring> static const char CPP_ARG0[] = "cppArg0"; +const char *CppGenerator::PYTHON_TO_CPPCONVERSION_STRUCT = "Shiboken::Conversions::PythonToCppConversion"; static inline QString reprFunction() { return QStringLiteral("__repr__"); } @@ -1171,7 +1172,8 @@ void CppGenerator::writeVirtualMethodNative(TextStream &s, s << "// Check return type\n"; if (func->typeReplaced(0).isEmpty()) { - s << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << " = " + s << PYTHON_TO_CPPCONVERSION_STRUCT + << ' ' << PYTHON_TO_CPP_VAR << " = " << cpythonIsConvertibleFunction(func->type()) << PYTHON_RETURN_VAR << ");\n" << "if (!" << PYTHON_TO_CPP_VAR << ") {\n"; @@ -1864,15 +1866,10 @@ static const char *fullName = ")" << fullPythonFunctionName(rfunc, true) << "\";\nSBK_UNUSED(fullName)\n"; if (maxArgs > 0) { s << "int overloadId = -1;\n" - << "PythonToCppFunc " << PYTHON_TO_CPP_VAR; - if (overloadData.pythonFunctionWrapperUsesListOfArguments()) { - s << "[] = { " << NULL_PTR; - for (int i = 1; i < maxArgs; ++i) - s << ", " << NULL_PTR; - s << " };\n"; - } else { - s << "{};\n"; - } + << PYTHON_TO_CPPCONVERSION_STRUCT << ' ' << PYTHON_TO_CPP_VAR; + if (overloadData.pythonFunctionWrapperUsesListOfArguments()) + s << '[' << maxArgs << ']'; + s << ";\n"; writeUnusedVariableCast(s, QLatin1String(PYTHON_TO_CPP_VAR)); } @@ -2684,8 +2681,7 @@ void CppGenerator::writePythonToCppTypeConversion(TextStream &s, if (!defaultValue.isEmpty()) s << "if (" << pythonToCppFunc << ") {\n" << indent; - s << "if (Shiboken::Conversions::isImplicitConversion(reinterpret_cast<PyTypeObject *>(" - << cpythonTypeNameExt(type) << "), " << pythonToCppFunc << "))\n" + s << "if (" << pythonToCppFunc << ".isValue())\n" << indent << pythonToCppFunc << '(' << pyIn << ", &" << cppOutAux << ");\n" << outdent << "else\n" << indent << pythonToCppCall << ";\n" << outdent; @@ -4816,7 +4812,7 @@ void CppGenerator::writeSetterFunctionPreamble(TextStream &s, const QString &nam << "return -1;\n" << outdent << "}\n"; - s << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << "{nullptr};\n" + s << PYTHON_TO_CPPCONVERSION_STRUCT << ' ' << PYTHON_TO_CPP_VAR << ";\n" << "if (!"; writeTypeCheck(s, type, QLatin1String("pyIn"), isNumber(type.typeEntry())); s << ") {\n" << indent @@ -4892,7 +4888,7 @@ void CppGenerator::writeRichCompareFunction(TextStream &s, writeCppSelfDefinition(s, context, false, false, true); writeUnusedVariableCast(s, QLatin1String(CPP_SELF_VAR)); s << "PyObject *" << PYTHON_RETURN_VAR << "{};\n" - << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << ";\n"; + << PYTHON_TO_CPPCONVERSION_STRUCT << ' ' << PYTHON_TO_CPP_VAR << ";\n"; writeUnusedVariableCast(s, QLatin1String(PYTHON_TO_CPP_VAR)); s << '\n'; @@ -6608,7 +6604,7 @@ void CppGenerator::writeDefaultSequenceMethods(TextStream &s, writeCppSelfDefinition(s, context); writeIndexError(s, QLatin1String("list assignment index out of range")); - s << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << ";\n" + s << PYTHON_TO_CPPCONVERSION_STRUCT << ' ' << PYTHON_TO_CPP_VAR << ";\n" << "if (!"; writeTypeCheck(s, itemType, QLatin1String("pyArg"), isNumber(itemType.typeEntry())); s << ") {\n"; diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.h b/sources/shiboken6/generator/shiboken/cppgenerator.h index 8f6a19ced..19041e3b0 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.h +++ b/sources/shiboken6/generator/shiboken/cppgenerator.h @@ -446,6 +446,7 @@ private: QHash<QString, QString> m_tpFuncs; static QString m_currentErrorCode; + static const char *PYTHON_TO_CPPCONVERSION_STRUCT; /// Helper class to set and restore the current error code. class ErrorCode { diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp index 795dae03c..e7dd58c58 100644 --- a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp +++ b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp @@ -1152,15 +1152,15 @@ QString ShibokenGenerator::cpythonIsConvertibleFunction(AbstractMetaType metaTyp QString result = QLatin1String("Shiboken::Conversions::"); if (metaType.isWrapperType()) { if (metaType.isPointer() || metaType.isValueTypeWithCopyConstructorOnly()) - result += QLatin1String("isPythonToCppPointerConvertible"); + result += u"pythonToCppPointerConversion"_qs; else if (metaType.referenceType() == LValueReference) - result += QLatin1String("isPythonToCppReferenceConvertible"); + result += u"pythonToCppReferenceConversion"_qs; else - result += QLatin1String("isPythonToCppValueConvertible"); + result += u"pythonToCppValueConversion"_qs; result += u'(' + cpythonTypeNameExt(metaType) + u", "_qs; return result; } - result += QLatin1String("isPythonToCppConvertible(") + converterObject(metaType); + result += u"pythonToCppConversion("_qs + converterObject(metaType); // Write out array sizes if known const AbstractMetaTypeList nestedArrayTypes = metaType.nestedArrayTypes(); if (!nestedArrayTypes.isEmpty() && nestedArrayTypes.constLast().isCppPrimitive()) { diff --git a/sources/shiboken6/libshiboken/sbkconverter.cpp b/sources/shiboken6/libshiboken/sbkconverter.cpp index 8fefb35cb..21f2ecae5 100644 --- a/sources/shiboken6/libshiboken/sbkconverter.cpp +++ b/sources/shiboken6/libshiboken/sbkconverter.cpp @@ -253,6 +253,15 @@ PythonToCppFunc isPythonToCppPointerConvertible(PyTypeObject *type, PyObject *py return sotp->converter->toCppPointerConversion.first(pyIn); } +PythonToCppConversion pythonToCppPointerConversion(PyTypeObject *type, PyObject *pyIn) +{ + if (pyIn == nullptr) + return {}; + if (PythonToCppFunc toCppPtr = isPythonToCppPointerConvertible(type, pyIn)) + return {toCppPtr, PythonToCppConversion::Pointer}; + return {}; +} + static inline PythonToCppFunc IsPythonToCppConvertible(const SbkConverter *converter, PyObject *pyIn) { assert(pyIn); @@ -269,11 +278,40 @@ PythonToCppFunc isPythonToCppValueConvertible(PyTypeObject *type, PyObject *pyIn return IsPythonToCppConvertible(sotp->converter, pyIn); } +PythonToCppConversion pythonToCppValueConversion(PyTypeObject *type, PyObject *pyIn) +{ + if (pyIn == nullptr) + return {}; + if (PythonToCppFunc toCppVal = isPythonToCppValueConvertible(type, pyIn)) + return {toCppVal, PythonToCppConversion::Value}; + return {}; +} + PythonToCppFunc isPythonToCppConvertible(const SbkConverter *converter, PyObject *pyIn) { return IsPythonToCppConvertible(converter, pyIn); } +PythonToCppConversion pythonToCppReferenceConversion(const SbkConverter *converter, PyObject *pyIn) +{ + if (converter->toCppPointerConversion.first) { + if (auto toCppPtr = converter->toCppPointerConversion.first(pyIn)) + return {toCppPtr, PythonToCppConversion::Pointer}; + } + for (const ToCppConversion &c : converter->toCppConversions) { + if (PythonToCppFunc toCppFunc = c.first(pyIn)) + return {toCppFunc, PythonToCppConversion::Value}; + } + return {}; +} + +PythonToCppConversion pythonToCppConversion(const SbkConverter *converter, PyObject *pyIn) +{ + if (auto func = IsPythonToCppConvertible(converter, pyIn)) + return {func, PythonToCppConversion::Value}; + return {}; +} + PythonToCppFunc isPythonToCppConvertible(const SbkArrayConverter *converter, int dim1, int dim2, PyObject *pyIn) { @@ -285,6 +323,14 @@ PythonToCppFunc isPythonToCppConvertible(const SbkArrayConverter *converter, return nullptr; } +LIBSHIBOKEN_API PythonToCppConversion pythonToCppConversion(const SbkArrayConverter *converter, + int dim1, int dim2, PyObject *pyIn) +{ + if (auto func = isPythonToCppConvertible(converter, dim1, dim2, pyIn)) + return {func, PythonToCppConversion::Value}; + return {}; +} + PythonToCppFunc isPythonToCppReferenceConvertible(PyTypeObject *type, PyObject *pyIn) { if (pyIn != Py_None) { @@ -295,6 +341,19 @@ PythonToCppFunc isPythonToCppReferenceConvertible(PyTypeObject *type, PyObject * return isPythonToCppValueConvertible(type, pyIn); } +PythonToCppConversion pythonToCppReferenceConversion(PyTypeObject *type, PyObject *pyIn) +{ + if (pyIn == nullptr) + return {}; + if (pyIn != Py_None) { + if (PythonToCppFunc toCppPtr = isPythonToCppPointerConvertible(type, pyIn)) + return {toCppPtr, PythonToCppConversion::Pointer}; + } + if (PythonToCppFunc toCppVal = isPythonToCppValueConvertible(type, pyIn)) + return {toCppVal, PythonToCppConversion::Value}; + return {}; +} + void nonePythonToCppNullPtr(PyObject *, void *cppOut) { assert(cppOut); diff --git a/sources/shiboken6/libshiboken/sbkconverter.h b/sources/shiboken6/libshiboken/sbkconverter.h index 5b25a8918..04dd25c75 100644 --- a/sources/shiboken6/libshiboken/sbkconverter.h +++ b/sources/shiboken6/libshiboken/sbkconverter.h @@ -220,11 +220,26 @@ LIBSHIBOKEN_API PyObject *copyToPython(const SbkConverter *converter, const void // Python -> C++ --------------------------------------------------------------------------- +struct PythonToCppConversion +{ + enum Type {Invalid, Pointer, Value}; + + operator bool() const { return type != Invalid; } + + void operator()(PyObject *po,void *cpp) const { function(po, cpp); } + + bool isValue() const { return type == Value; } + + PythonToCppFunc function = nullptr; + Type type = Invalid; +}; + /** * Returns a Python to C++ conversion function if the Python object is convertible to a C++ pointer. * It returns NULL if the Python object is not convertible to \p type. */ LIBSHIBOKEN_API PythonToCppFunc isPythonToCppPointerConvertible(PyTypeObject *type, PyObject *pyIn); +LIBSHIBOKEN_API PythonToCppConversion pythonToCppPointerConversion(PyTypeObject *type, PyObject *pyIn); /** * Returns a Python to C++ conversion function if the Python object is convertible to a C++ value. @@ -233,6 +248,7 @@ LIBSHIBOKEN_API PythonToCppFunc isPythonToCppPointerConvertible(PyTypeObject *ty * It returns NULL if the Python object is not convertible to \p type. */ LIBSHIBOKEN_API PythonToCppFunc isPythonToCppValueConvertible(PyTypeObject *type, PyObject *pyIn); +LIBSHIBOKEN_API PythonToCppConversion pythonToCppValueConversion(PyTypeObject *type, PyObject *pyIn); /** * Returns a Python to C++ conversion function if the Python object is convertible to a C++ reference. @@ -241,11 +257,17 @@ LIBSHIBOKEN_API PythonToCppFunc isPythonToCppValueConvertible(PyTypeObject *type * It returns NULL if the Python object is not convertible to \p type. */ LIBSHIBOKEN_API PythonToCppFunc isPythonToCppReferenceConvertible(PyTypeObject *type, PyObject *pyIn); +LIBSHIBOKEN_API PythonToCppConversion pythonToCppReferenceConversion(PyTypeObject *type, PyObject *pyIn); /// This is the same as isPythonToCppValueConvertible function. LIBSHIBOKEN_API PythonToCppFunc isPythonToCppConvertible(const SbkConverter *converter, PyObject *pyIn); +LIBSHIBOKEN_API PythonToCppConversion pythonToCppReferenceConversion(const SbkConverter *converter, PyObject *pyIn); + +LIBSHIBOKEN_API PythonToCppConversion pythonToCppConversion(const SbkConverter *converter, PyObject *pyIn); LIBSHIBOKEN_API PythonToCppFunc isPythonToCppConvertible(const SbkArrayConverter *converter, int dim1, int dim2, PyObject *pyIn); +LIBSHIBOKEN_API PythonToCppConversion pythonToCppConversion(const SbkArrayConverter *converter, + int dim1, int dim2, PyObject *pyIn); /** * Returns the C++ pointer for the \p pyIn object cast to the type passed via \p desiredType. @@ -273,7 +295,7 @@ LIBSHIBOKEN_API void nonePythonToCppNullPtr(PyObject *, void *cppOut); * It is used when C++ expects a reference argument, so it may be the same object received * from Python, or another created through implicit conversion. */ -LIBSHIBOKEN_API bool isImplicitConversion(PyTypeObject *type, PythonToCppFunc toCpp); +[[deprecated]] LIBSHIBOKEN_API bool isImplicitConversion(PyTypeObject *type, PythonToCppFunc toCpp); /// Registers a converter with a type name that may be used to retrieve the converter. LIBSHIBOKEN_API void registerConverterName(SbkConverter *converter, const char *typeName); |