aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2021-09-13 13:45:54 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2021-09-24 13:52:35 +0200
commit79b32f4d4b5154ba8001bafc481fb6edacc10280 (patch)
tree2ebd4470b1eef8e9cd231213901ac6ca2c454f06
parentd9bad33ad2cd0e49e22c82f8d05422274cbbf1c8 (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>
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.cpp26
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.h1
-rw-r--r--sources/shiboken6/generator/shiboken/shibokengenerator.cpp8
-rw-r--r--sources/shiboken6/libshiboken/sbkconverter.cpp59
-rw-r--r--sources/shiboken6/libshiboken/sbkconverter.h24
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);