From 8c9037dc83fbdbb0b9913961fbe7f84066630e18 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Tue, 5 Sep 2017 13:41:43 +0200 Subject: Remove dead / unused code regarding conversions There's a lot of code that was previously used for doing conversions between C++ / Python types (apparently relying on extensive RTTI / typeid manipulations), which got superseded by a cleaner templated approach. The old code was left behind, and there were a few instances where it was still used even though it wasn't needed, like in QtScript typesystem XML and shiboken's enum handling. Remove the old code, apply the small changes needed to make it work with new the code. This is cleanup to reduce the confusion regarding conversion behavior, and also preparation for a proper implementation of handling "void*" types. Change-Id: I8f16bb31436f9a677bb2d64c7197c4375005b656 Reviewed-by: Friedemann Kleint --- .../PySide2/QtCore/typesystem_core_common.xml | 4 +- .../QtScript/qscript_value_iterator_glue.cpp | 3 + .../pyside2/PySide2/QtScript/typesystem_script.xml | 4 +- sources/pyside2/libpyside/CMakeLists.txt | 1 - sources/pyside2/libpyside/globalreceiver.cpp | 1 - sources/pyside2/libpyside/globalreceiverv2.cpp | 1 - sources/pyside2/libpyside/pyside.cpp | 5 +- sources/pyside2/libpyside/pysideconversions.h | 275 -------- sources/pyside2/libpyside/signalmanager.cpp.in | 28 +- .../shiboken2/generator/shiboken2/cppgenerator.cpp | 20 - .../generator/shiboken2/headergenerator.cpp | 2 +- sources/shiboken2/libshiboken/CMakeLists.txt | 3 - sources/shiboken2/libshiboken/basewrapper.cpp | 4 +- sources/shiboken2/libshiboken/conversions.h | 731 --------------------- sources/shiboken2/libshiboken/helper.cpp | 1 + sources/shiboken2/libshiboken/helper.h | 41 -- sources/shiboken2/libshiboken/sbkconverter.cpp | 1 + sources/shiboken2/libshiboken/sbkconverter.h | 33 +- sources/shiboken2/libshiboken/sbkconverter_p.h | 23 +- sources/shiboken2/libshiboken/sbkenum.cpp | 6 - sources/shiboken2/libshiboken/shiboken.h | 2 - sources/shiboken2/libshiboken/typeresolver.cpp | 162 ----- sources/shiboken2/libshiboken/typeresolver.h | 139 ---- 23 files changed, 53 insertions(+), 1437 deletions(-) create mode 100644 sources/pyside2/PySide2/QtScript/qscript_value_iterator_glue.cpp delete mode 100644 sources/pyside2/libpyside/pysideconversions.h delete mode 100644 sources/shiboken2/libshiboken/conversions.h delete mode 100644 sources/shiboken2/libshiboken/typeresolver.cpp delete mode 100644 sources/shiboken2/libshiboken/typeresolver.h (limited to 'sources') diff --git a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml index 41a20a617..951d943ee 100644 --- a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml +++ b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml @@ -313,7 +313,6 @@ - if (!%in.isValid()) @@ -756,7 +755,8 @@ - + + diff --git a/sources/pyside2/PySide2/QtScript/qscript_value_iterator_glue.cpp b/sources/pyside2/PySide2/QtScript/qscript_value_iterator_glue.cpp new file mode 100644 index 000000000..fd9cd84a3 --- /dev/null +++ b/sources/pyside2/PySide2/QtScript/qscript_value_iterator_glue.cpp @@ -0,0 +1,3 @@ +%PYARG_0 = Shiboken::Object::newObject( + reinterpret_cast(Shiboken::SbkType< ::QScriptValueIterator >()), + new QScriptValueIterator(*%CPPSELF), true, true); diff --git a/sources/pyside2/PySide2/QtScript/typesystem_script.xml b/sources/pyside2/PySide2/QtScript/typesystem_script.xml index 9dbd107a1..46ee824c1 100644 --- a/sources/pyside2/PySide2/QtScript/typesystem_script.xml +++ b/sources/pyside2/PySide2/QtScript/typesystem_script.xml @@ -106,9 +106,7 @@ - - %PYARG_0 = Shiboken::createWrapper(new QScriptValueIterator(*%CPPSELF), true, true); - + diff --git a/sources/pyside2/libpyside/CMakeLists.txt b/sources/pyside2/libpyside/CMakeLists.txt index 05e383307..1cddebc07 100644 --- a/sources/pyside2/libpyside/CMakeLists.txt +++ b/sources/pyside2/libpyside/CMakeLists.txt @@ -120,7 +120,6 @@ set(libpyside_HEADERS dynamicqmetaobject.h globalreceiver.h pysideclassinfo.h - pysideconversions.h pysidemacros.h signalmanager.h pyside.h diff --git a/sources/pyside2/libpyside/globalreceiver.cpp b/sources/pyside2/libpyside/globalreceiver.cpp index e183e09ba..5e0aa0d66 100644 --- a/sources/pyside2/libpyside/globalreceiver.cpp +++ b/sources/pyside2/libpyside/globalreceiver.cpp @@ -49,7 +49,6 @@ #include #include -#include "typeresolver.h" #include "signalmanager.h" #define RECEIVER_DESTROYED_SLOT_NAME "__receiverDestroyed__(QObject*)" diff --git a/sources/pyside2/libpyside/globalreceiverv2.cpp b/sources/pyside2/libpyside/globalreceiverv2.cpp index a79d43c20..9e9bccbaf 100644 --- a/sources/pyside2/libpyside/globalreceiverv2.cpp +++ b/sources/pyside2/libpyside/globalreceiverv2.cpp @@ -48,7 +48,6 @@ #include #include -#include "typeresolver.h" #include "signalmanager.h" #define RECEIVER_DESTROYED_SLOT_NAME "__receiverDestroyed__(QObject*)" diff --git a/sources/pyside2/libpyside/pyside.cpp b/sources/pyside2/libpyside/pyside.cpp index d4e867c61..17366ce6e 100644 --- a/sources/pyside2/libpyside/pyside.cpp +++ b/sources/pyside2/libpyside/pyside.cpp @@ -50,14 +50,15 @@ #include "dynamicqmetaobject.h" #include "destroylistener.h" +#include #include #include -#include #include +#include #include -#include #include #include +#include #include #include #include diff --git a/sources/pyside2/libpyside/pysideconversions.h b/sources/pyside2/libpyside/pysideconversions.h deleted file mode 100644 index ed8002fae..000000000 --- a/sources/pyside2/libpyside/pysideconversions.h +++ /dev/null @@ -1,275 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PYSIDECONVERSIONS_H -#define PYSIDECONVERSIONS_H - -#include -#include -#include -#include - -template -struct QtDictConverter -{ - static inline bool checkType(PyObject* pyObj) - { - return isConvertible(pyObj); - } - - static inline bool isConvertible(PyObject* pyObj) - { - if (PyObject_TypeCheck(pyObj, Shiboken::SbkType())) - return true; - - if ((Shiboken::SbkType() && Shiboken::Object::checkType(pyObj)) || !PyDict_Check(pyObj)) - return false; - - PyObject* key; - PyObject* value; - Py_ssize_t pos = 0; - - while (PyDict_Next(pyObj, &pos, &key, &value)) { - if (!Shiboken::Converter::isConvertible(key) - && !Shiboken::Converter::isConvertible(value)) { - return false; - } - } - return true; - } - - static inline PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast(cppObj)); } - static inline PyObject* toPython(const QtDict& cppobj) - { - PyObject* result = PyDict_New(); - typename QtDict::const_iterator it = cppobj.begin(); - - for (; it != cppobj.end(); ++it) { - Shiboken::AutoDecRef keyObj(Shiboken::Converter::toPython(it.key())); - Shiboken::AutoDecRef valueObj(Shiboken::Converter::toPython(it.value())); - PyDict_SetItem(result, keyObj, valueObj); - } - - return result; - } - static inline QtDict toCpp(PyObject* pyobj) - { - if (PyObject_TypeCheck(pyobj, Shiboken::SbkType())) - return *reinterpret_cast(Shiboken::Object::cppPointer(reinterpret_cast(pyobj), Shiboken::SbkType())); - - QtDict result; - - PyObject* key; - PyObject* value; - Py_ssize_t pos = 0; - - while (PyDict_Next(pyobj, &pos, &key, &value)) - result[Shiboken::Converter::toCpp(key)] = Shiboken::Converter::toCpp(value); - return result; - } -}; - -template -struct QtMultiMapConverter -{ - static inline bool checkType(PyObject* pyObj) - { - return isConvertible(pyObj); - } - - static inline bool isConvertible(PyObject* pyObj) - { - if (PyObject_TypeCheck(pyObj, Shiboken::SbkType())) - return true; - - if ((Shiboken::SbkType() && Shiboken::Object::checkType(pyObj)) || !PyDict_Check(pyObj)) - return false; - - PyObject* key; - PyObject* value; - Py_ssize_t pos = 0; - - while (PyDict_Next(pyObj, &pos, &key, &value)) { - if (!Shiboken::Converter::isConvertible(key)) { - if (PySequence_Check(value)) { - for (int i = 0, max = PySequence_Length(value); i < max; ++i) { - Shiboken::AutoDecRef item(PySequence_GetItem(value, i)); - if (!Shiboken::Converter::isConvertible(value)) - return false; - } - } else if (!Shiboken::Converter::isConvertible(value)) { - return false; - } - } - } - return true; - } - - static inline PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast(cppObj)); } - static inline PyObject* toPython(const MultiMap& cppObj) - { - PyObject* result = PyDict_New(); - typename MultiMap::const_iterator it = cppObj.begin(); - - for (; it != cppObj.end(); ++it) { - Shiboken::AutoDecRef key(Shiboken::Converter::toPython(it.key())); - Shiboken::AutoDecRef value(Shiboken::Converter::toPython(it.value())); - - PyObject* values = PyDict_GetItem(result, key); - bool decRefValues = !values; - if (!values) - values = PyList_New(0); - PyList_Append(values, value); - PyDict_SetItem(result, key, values); - if (decRefValues) { - Py_DECREF(values); - } - } - - return result; - } - - static inline MultiMap toCpp(PyObject* pyObj) - { - if (PyObject_TypeCheck(pyObj, Shiboken::SbkType())) - return *reinterpret_cast(Shiboken::Object::cppPointer(reinterpret_cast(pyObj), Shiboken::SbkType())); - - MultiMap result; - - PyObject* key; - PyObject* value; - Py_ssize_t pos = 0; - - while (PyDict_Next(pyObj, &pos, &key, &value)) - result[Shiboken::Converter::toCpp(key)] = Shiboken::Converter::toCpp(value); - return result; - } -}; - -template -struct QSequenceConverter -{ - static inline bool checkType(PyObject* pyObj) - { - return isConvertible(pyObj); - } - - static inline bool isConvertible(PyObject* pyObj) - { - if (PyObject_TypeCheck(pyObj, Shiboken::SbkType())) - return true; - if ((Shiboken::SbkType() && Shiboken::Object::checkType(pyObj)) || !PySequence_Check(pyObj)) - return false; - for (int i = 0, max = PySequence_Length(pyObj); i < max; ++i) { - Shiboken::AutoDecRef item(PySequence_GetItem(pyObj, i)); - if (!Shiboken::Converter::isConvertible(item)) - return false; - } - return true; - } - static inline PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast(cppObj)); } - static PyObject* toPython(const T& cppobj) - { - PyObject* result = PyList_New((int) cppobj.size()); - typename T::const_iterator it = cppobj.begin(); - for (int idx = 0; it != cppobj.end(); ++it, ++idx) { - typename T::value_type vh(*it); - PyList_SET_ITEM(result, idx, Shiboken::Converter::toPython(vh)); - } - return result; - } - static T toCpp(PyObject* pyobj) - { - if (PyObject_TypeCheck(pyobj, Shiboken::SbkType())) - return *reinterpret_cast(Shiboken::Object::cppPointer(reinterpret_cast(pyobj), Shiboken::SbkType())); - - Shiboken::AutoDecRef fastSequence(PySequence_Fast(pyobj, "Invalid sequence object")); - T result; - for (int i = 0; i < PySequence_Size(pyobj); i++) { - PyObject* pyItem = PySequence_Fast_GET_ITEM(fastSequence.object(), i); - result << Shiboken::Converter::toCpp(pyItem); - } - return result; - } -}; - - -template -struct QFlagsConverter -{ - static inline bool checkType(PyObject* pyObj) - { - return PyObject_TypeCheck(pyObj, Shiboken::SbkType()); - } - - static inline bool isConvertible(PyObject* pyObj) - { - return PyObject_TypeCheck(pyObj, Shiboken::SbkType()) - || PyObject_TypeCheck(pyObj, Shiboken::SbkType()); - } - - static inline PyObject* toPython(void* cppObj) - { - return toPython(*reinterpret_cast(cppObj)); - } - - static inline PyObject* toPython(const T& cppObj) - { - return reinterpret_cast(PySide::QFlags::newObject(cppObj, Shiboken::SbkType())); - } - - static inline T toCpp(PyObject* pyObj) - { - /* this was long. Needed int in Qt5 */ - int val = 0; - if (Shiboken::Enum::check(pyObj)) { - val = Shiboken::Enum::getValue(pyObj); - } else if (PyObject_TypeCheck(pyObj, Shiboken::SbkType())) { - val = PySide::QFlags::getValue(reinterpret_cast(pyObj)); - } else if (PyNumber_Check(pyObj)) { - Shiboken::AutoDecRef pyLong(PyNumber_Long(pyObj)); - val = PyLong_AsLong(pyLong.object()); - } else { - PyErr_BadArgument(); - } - return T(QFlag(val)); - } -}; - -#endif diff --git a/sources/pyside2/libpyside/signalmanager.cpp.in b/sources/pyside2/libpyside/signalmanager.cpp.in index 473057cbc..8ede09610 100644 --- a/sources/pyside2/libpyside/signalmanager.cpp.in +++ b/sources/pyside2/libpyside/signalmanager.cpp.in @@ -55,10 +55,10 @@ #include #include #include -#include #include +#include #include -#include +#include // These private headers are needed to throw JavaScript exceptions #if @QML_PRIVATE_API_SUPPORT@ @@ -214,30 +214,6 @@ QDataStream &operator>>(QDataStream& in, PyObjectWrapper& myObj) }; -namespace Shiboken { - -template<> -struct Converter -{ - static PySide::PyObjectWrapper toCpp(PyObject* obj) - { - return PySide::PyObjectWrapper(obj); - } - - static PyObject* toPython(void* obj) - { - return toPython(*reinterpret_cast(obj)); - } - - static PyObject* toPython(const PySide::PyObjectWrapper& obj) - { - Py_INCREF((PyObject*)obj); - return obj; - } -}; - -}; - using namespace PySide; struct SignalManager::SignalManagerPrivate diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index 6cc148140..a2b497132 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -234,7 +234,6 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) s << "#include " << endl; } - s << "#include " << endl; s << "#include " << endl; if (usePySideExtensions() && metaClass->isQObject()) { s << "#include " << endl; @@ -3485,7 +3484,6 @@ void CppGenerator::writeEnumConverterInitialization(QTextStream& s, const TypeEn writeAddPythonToCppConversion(s, QLatin1String("converter"), toCpp, isConv); } - s << INDENT << "Shiboken::Enum::setTypeConverter(" << enumPythonType << ", converter);" << endl; s << INDENT << "Shiboken::Enum::setTypeConverter(" << enumPythonType << ", converter);" << endl; QStringList cppSignature = enumType->qualifiedCppName().split(QLatin1String("::"), QString::SkipEmptyParts); while (!cppSignature.isEmpty()) { @@ -5509,24 +5507,6 @@ bool CppGenerator::finishGeneration() cppSignature.removeFirst(); } } - // Register type resolver for all containers found in signals. - QSet typeResolvers; - foreach (AbstractMetaClass* metaClass, classes()) { - if (!metaClass->isQObject() || !metaClass->typeEntry()->generateCode()) - continue; - foreach (AbstractMetaFunction* func, metaClass->functions()) { - if (func->isSignal()) { - foreach (AbstractMetaArgument* arg, func->arguments()) { - if (arg->type()->isContainer()) { - QString value = translateType(arg->type(), metaClass, ExcludeConst | ExcludeReference); - if (value.startsWith(QLatin1String("::"))) - value.remove(0, 2); - typeResolvers << QMetaObject::normalizedType(value.toUtf8().constData()); - } - } - } - } - } s << endl; if (maxTypeIndex) diff --git a/sources/shiboken2/generator/shiboken2/headergenerator.cpp b/sources/shiboken2/generator/shiboken2/headergenerator.cpp index 27a84f6a9..7158c370b 100644 --- a/sources/shiboken2/generator/shiboken2/headergenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/headergenerator.cpp @@ -466,7 +466,7 @@ bool HeaderGenerator::finishGeneration() } s << "#include " << endl; - s << "#include " << endl; + s << "#include " << endl; s << "#include " << endl; s << "#include " << endl; s << "#include " << endl; diff --git a/sources/shiboken2/libshiboken/CMakeLists.txt b/sources/shiboken2/libshiboken/CMakeLists.txt index 0c954aa07..d2553369b 100644 --- a/sources/shiboken2/libshiboken/CMakeLists.txt +++ b/sources/shiboken2/libshiboken/CMakeLists.txt @@ -35,7 +35,6 @@ sbkmodule.cpp sbkstring.cpp bindingmanager.cpp threadstatesaver.cpp -typeresolver.cpp shibokenbuffer.cpp signature.cpp qapp_macro.cpp @@ -56,7 +55,6 @@ install(FILES autodecref.h basewrapper.h bindingmanager.h - conversions.h gilstate.h helper.h sbkconverter.h @@ -68,7 +66,6 @@ install(FILES shiboken.h shibokenmacros.h threadstatesaver.h - typeresolver.h shibokenbuffer.h sbkpython.h signature.h diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp index 0d8758cee..ff9158d66 100644 --- a/sources/shiboken2/libshiboken/basewrapper.cpp +++ b/sources/shiboken2/libshiboken/basewrapper.cpp @@ -39,10 +39,11 @@ #include "basewrapper.h" #include "basewrapper_p.h" +#include "bindingmanager.h" #include "sbkconverter.h" #include "sbkenum.h" +#include "sbkstring.h" #include "autodecref.h" -#include "typeresolver.h" #include "gilstate.h" #include #include @@ -552,7 +553,6 @@ void init() Module::init(); Conversions::init(); - initTypeResolver(); PyEval_InitThreads(); //Init private data diff --git a/sources/shiboken2/libshiboken/conversions.h b/sources/shiboken2/libshiboken/conversions.h deleted file mode 100644 index a21fa0c2b..000000000 --- a/sources/shiboken2/libshiboken/conversions.h +++ /dev/null @@ -1,731 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef CONVERSIONS_H -#define CONVERSIONS_H - -#include "sbkpython.h" -#include -#include - -#include "sbkstring.h" -#include "sbkenum.h" -#include "basewrapper.h" -#include "bindingmanager.h" -#include "sbkdbg.h" - -// When the user adds a function with an argument unknown for the typesystem, the generator writes type checks as -// TYPENAME_Check, so this macro allows users to add PyObject arguments to their added functions. -#define PyObject_Check(X) true -#define SbkChar_Check(X) (SbkNumber_Check(X) || Shiboken::String::checkChar(X)) -#include "autodecref.h" - -namespace Shiboken -{ -/** -* This function template is used to get the PyTypeObject of a C++ type T. -* All implementations should be provided by template specializations generated by the generator when -* T isn't a C++ primitive type. -* \see SpecialCastFunction -*/ -template -PyTypeObject* SbkType() -{ - return 0; -} - -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType() { return &PyBool_Type; } -template<> inline PyTypeObject* SbkType() { return &PyFloat_Type; } -template<> inline PyTypeObject* SbkType() { return &PyFloat_Type; } -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } - -/** - * Convenience template to create wrappers using the proper Python type for a given C++ class instance. - */ -template -inline PyObject* createWrapper(const T* cppobj, bool hasOwnership = false, bool isExactType = false) -{ - const char* typeName = 0; - if (!isExactType) - typeName = typeid(*const_cast(cppobj)).name(); - return Object::newObject(reinterpret_cast(SbkType()), - const_cast(cppobj), hasOwnership, isExactType, typeName); -} - -// Base Conversions ---------------------------------------------------------- -// The basic converter must be empty to avoid object types being converted by value. -template struct Converter {}; - -// Pointer conversion specialization for value types. -template -struct Converter -{ - static inline bool checkType(PyObject* pyObj) - { - return Converter::checkType(pyObj); - } - - static inline bool isConvertible(PyObject* pyObj) - { - return pyObj == Py_None || PyObject_TypeCheck(pyObj, SbkType()); - } - - static PyObject* toPython(const T* cppobj) - { - if (!cppobj) - Py_RETURN_NONE; - PyObject* pyobj = reinterpret_cast(BindingManager::instance().retrieveWrapper(cppobj)); - if (pyobj) - Py_INCREF(pyobj); - else - pyobj = createWrapper(cppobj); - return pyobj; - } - - static T* toCpp(PyObject* pyobj) - { - if (PyObject_TypeCheck(pyobj, SbkType())) - return reinterpret_cast(Object::cppPointer(reinterpret_cast(pyobj), SbkType())); - else if (Converter::isConvertible(pyobj)) - return new T(Converter::toCpp(pyobj)); - else if (pyobj == Py_None) - return 0; - - assert(false); - return 0; - } -}; -template struct Converter : Converter {}; - -// Specialization for reference conversions. -template -struct Converter -{ - static inline bool checkType(PyObject* pyObj) { return Converter::checkType(pyObj); } - static inline bool isConvertible(PyObject* pyObj) { return Converter::isConvertible(pyObj); } - static inline PyObject* toPython(const T& cppobj) { return Converter::toPython(&cppobj); } - static inline T& toCpp(PyObject* pyobj) { return *Converter::toCpp(pyobj); } -}; - -// Void pointer conversions. -template<> -struct Converter -{ - static inline bool checkType(PyObject *) { return false; } - static inline bool isConvertible(PyObject *) { return true; } - static PyObject* toPython(void* cppobj) - { - if (!cppobj) - Py_RETURN_NONE; - PyObject *result = reinterpret_cast(cppobj); - Py_INCREF(result); - return result; - } - static void* toCpp(PyObject* pyobj) { return pyobj; } -}; - -// Base converter meant to be inherited by converters for classes that could be -// passed by value. -// Example: "struct Converter : ValueTypeConverter" -template -struct ValueTypeConverter -{ - static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType()); } - - // The basic version of this method also tries to use the extended 'isConvertible' method. - static inline bool isConvertible(PyObject* pyobj) - { - if (PyObject_TypeCheck(pyobj, SbkType())) - return true; - SbkObjectType* shiboType = reinterpret_cast(SbkType()); - return ObjectType::isExternalConvertible(shiboType, pyobj); - } - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } - static inline PyObject* toPython(const T& cppobj) - { - PyObject* obj = createWrapper(new T(cppobj), true, true); -// SbkBaseWrapper_setContainsCppWrapper(obj, SbkTypeInfo::isCppWrapper); - return obj; - } - // Classes with implicit conversions are expected to reimplement 'toCpp' to build T from - // its various implicit constructors. Even classes without implicit conversions could - // get some of those via other modules defining conversion operator for them, thus - // the basic Converter for value types checks for extended conversion and tries to - // use them if it is the case. - static inline T toCpp(PyObject* pyobj) - { - if (!PyObject_TypeCheck(pyobj, SbkType())) { - SbkObjectType* shiboType = reinterpret_cast(SbkType()); - if (ObjectType::hasExternalCppConversions(shiboType) && isConvertible(pyobj)) { - T* cptr = reinterpret_cast(ObjectType::callExternalCppConversion(shiboType, pyobj)); - const T result = *cptr; - delete cptr; - return result; - } - assert(false); - } - return *reinterpret_cast(Object::cppPointer(reinterpret_cast(pyobj), SbkType())); - } -}; - -// Base converter meant to be inherited by converters for abstract classes and object types -// (i.e. classes with private copy constructors and = operators). -// Example: "struct Converter : ObjectTypeConverter" -template -struct ObjectTypeConverter -{ - static inline bool checkType(PyObject* pyObj) { return pyObj == Py_None || PyObject_TypeCheck(pyObj, SbkType()); } - /// Py_None objects are the only objects convertible to an object type (in the form of a NULL pointer). - static inline bool isConvertible(PyObject* pyObj) { return pyObj == Py_None || PyObject_TypeCheck(pyObj, SbkType()); } - /// Convenience overload that calls "toPython(const T*)" method. - static inline PyObject* toPython(void* cppobj) { return toPython(reinterpret_cast(cppobj)); } - /// Returns a new Python wrapper for the C++ object or an existing one with its reference counter incremented. - static PyObject* toPython(const T* cppobj) - { - if (!cppobj) - Py_RETURN_NONE; - PyObject* pyobj = reinterpret_cast(BindingManager::instance().retrieveWrapper(cppobj)); - if (pyobj) - Py_INCREF(pyobj); - else - pyobj = createWrapper(cppobj); - return pyobj; - } - /// Returns the wrapped C++ pointer casted properly, or a NULL pointer if the argument is a Py_None. - static T* toCpp(PyObject* pyobj) - { - if (pyobj == Py_None) - return 0; - SbkObject *sbkObj = reinterpret_cast(pyobj); - SbkObjectType* shiboType = reinterpret_cast(pyobj->ob_type); - if (ObjectType::hasCast(shiboType)) - return reinterpret_cast(ObjectType::cast(shiboType, sbkObj, SbkType())); - return reinterpret_cast(Object::cppPointer(sbkObj, SbkType())); - } -}; - -template -struct ObjectTypeReferenceConverter : ObjectTypeConverter -{ - static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType()); } - static inline bool isConvertible(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType()); } - static inline PyObject* toPython(const T& cppobj) { return Converter::toPython(&cppobj); } - static inline T& toCpp(PyObject* pyobj) - { - T* t = Converter::toCpp(pyobj); - assert(t); - return *t; - } -}; - -// PyObject* specialization to avoid converting what doesn't need to be converted. -template<> -struct Converter : ObjectTypeConverter -{ - static inline PyObject* toCpp(PyObject* pyobj) { return pyobj; } -}; - -// Primitive Conversions ------------------------------------------------------ -template <> -struct Converter -{ - static inline bool checkType(PyObject* pyobj) { return PyBool_Check(pyobj); } - static inline bool isConvertible(PyObject* pyobj) { return PyInt_Check(pyobj); } - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } - static inline PyObject* toPython(bool cppobj) { return PyBool_FromLong(cppobj); } - static inline bool toCpp(PyObject* pyobj) { return PyInt_AS_LONG(pyobj) != 0; } -}; - -/** - * Helper template for checking if a value overflows when casted to type T - */ -template::is_signed > -struct OverFlowChecker; - -template -struct OverFlowChecker -{ - static bool check(const PY_LONG_LONG& value) - { - return value < std::numeric_limits::min() || value > std::numeric_limits::max(); - } -}; - -template -struct OverFlowChecker -{ - static bool check(const PY_LONG_LONG& value) - { - return value < 0 || static_cast(value) > std::numeric_limits::max(); - } -}; - -template<> -struct OverFlowChecker -{ - static bool check(const PY_LONG_LONG &) - { - return false; - } -}; - -template<> -struct OverFlowChecker -{ - static bool check(const double &) - { - return false; - } -}; - -template<> -struct OverFlowChecker -{ - static bool check(const double& value) - { - return value < std::numeric_limits::min() || value > std::numeric_limits::max(); - } -}; - -template -struct Converter_PyInt -{ - static inline bool checkType(PyObject* pyobj) { return PyInt_Check(pyobj); } - static inline bool isConvertible(PyObject* pyobj) { return SbkNumber_Check(pyobj); } - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } - static inline PyObject* toPython(const PyIntEquiv& cppobj) { return PyInt_FromLong((long) cppobj); } - static PyIntEquiv toCpp(PyObject* pyobj) - { - if (PyFloat_Check(pyobj)) { - double d_result = PyFloat_AS_DOUBLE(pyobj); - // If cast to long directly it could overflow silently - if (OverFlowChecker::check(d_result)) - PyErr_SetObject(PyExc_OverflowError, 0); - return static_cast(d_result); - } else { - PY_LONG_LONG result = PyLong_AsLongLong(pyobj); - if (OverFlowChecker::check(result)) - PyErr_SetObject(PyExc_OverflowError, 0); - return static_cast(result); - } - } -}; - -template -struct Converter_PyULongInt : Converter_PyInt -{ - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } - static inline PyObject* toPython(const T& cppobj) { return PyLong_FromUnsignedLong(cppobj); } -}; - -/// Specialization to convert char and unsigned char, it accepts Python numbers and strings with just one character. -template -struct CharConverter -{ - static inline bool checkType(PyObject* pyobj) { return SbkChar_Check(pyobj); } - static inline bool isConvertible(PyObject* pyobj) { return SbkChar_Check(pyobj); } - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } - static inline PyObject* toPython(const CharType& cppobj) { return PyInt_FromLong(cppobj); } - static CharType toCpp(PyObject* pyobj) - { - if (PyBytes_Check(pyobj)) { - assert(PyBytes_GET_SIZE(pyobj) == 1); // This check is made on SbkChar_Check - return PyBytes_AS_STRING(pyobj)[0]; - } else if (PyInt_Check(pyobj)) { - PY_LONG_LONG result = PyInt_AsUnsignedLongLongMask(pyobj); - if (OverFlowChecker::check(result)) - PyErr_SetObject(PyExc_OverflowError, 0); - return result; - } else if (Shiboken::String::check(pyobj)) { - return Shiboken::String::toCString(pyobj)[0]; - } else { - return 0; - } - } -}; - -template <> struct Converter : Converter_PyULongInt {}; -template <> struct Converter : Converter_PyULongInt {}; -template <> struct Converter : CharConverter -{ - // Should we really return a string? - using CharConverter::toPython; - using CharConverter::isConvertible; - using CharConverter::toCpp; - - - static inline bool isConvertible(PyObject* pyobj) { - return SbkChar_Check(pyobj); - } - - static inline PyObject* toPython(const char& cppObj) { - return Shiboken::String::fromFormat("%c", cppObj); - } - - static char toCpp(PyObject* pyobj) - { - if (PyBytes_Check(pyobj)) { - assert(PyBytes_GET_SIZE(pyobj) == 1); // This check is made on SbkChar_Check - return PyBytes_AS_STRING(pyobj)[0]; - } else if (PyInt_Check(pyobj)) { - PY_LONG_LONG result = PyInt_AsUnsignedLongLongMask(pyobj); - if (OverFlowChecker::check(result)) - PyErr_SetObject(PyExc_OverflowError, 0); - return char(result); - } else if (Shiboken::String::check(pyobj)) { - return Shiboken::String::toCString(pyobj)[0]; - } else { - return 0; - } - } -}; -template <> struct Converter : CharConverter {}; -template <> struct Converter : CharConverter {}; -template <> struct Converter : Converter_PyInt {}; -template <> struct Converter : Converter_PyInt {}; -template <> struct Converter : Converter_PyInt {}; -template <> struct Converter : Converter_PyInt {}; - -template <> -struct Converter -{ - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } - static inline PyObject* toPython(PY_LONG_LONG cppobj) { return PyLong_FromLongLong(cppobj); } - static inline PY_LONG_LONG toCpp(PyObject* pyobj) { return (PY_LONG_LONG) PyLong_AsLongLong(pyobj); } -}; - -template <> -struct Converter -{ - static inline PyObject* toPython(void* cppobj) - { - return toPython(*reinterpret_cast(cppobj)); - } - static inline PyObject* toPython(unsigned PY_LONG_LONG cppobj) - { - return PyLong_FromUnsignedLongLong(cppobj); - } - static inline unsigned PY_LONG_LONG toCpp(PyObject* pyobj) - { -#if PY_MAJOR_VERSION >= 3 - if (!PyLong_Check(pyobj)) { - PyErr_SetString(PyExc_TypeError, "Invalid type for unsigned long long conversion"); - return 0; - } - - return PyLong_AsUnsignedLongLong(pyobj); -#else - if (PyInt_Check(pyobj)) { - long result = (unsigned PY_LONG_LONG) PyInt_AsLong(pyobj); - if (result < 0) { - PyErr_SetObject(PyExc_OverflowError, 0); - return 0; - } else - return (unsigned PY_LONG_LONG) result; - } else if (PyLong_Check(pyobj)) { - return (unsigned PY_LONG_LONG) PyLong_AsUnsignedLongLong(pyobj); - } else { - PyErr_SetString(PyExc_TypeError, "Invalid type for unsigned long long conversion"); - return 0; - } -#endif // Python 2 - } -}; - -template -struct Converter_PyFloat -{ - static inline bool checkType(PyObject* obj) { return PyFloat_Check(obj); } - static inline bool isConvertible(PyObject* obj) { return SbkNumber_Check(obj); } - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } - static inline PyObject* toPython(PyFloatEquiv cppobj) { return PyFloat_FromDouble((double) cppobj); } - static inline PyFloatEquiv toCpp(PyObject* pyobj) - { - if (PyInt_Check(pyobj) || PyLong_Check(pyobj)) - return (PyFloatEquiv) PyLong_AsLong(pyobj); - return (PyFloatEquiv) PyFloat_AsDouble(pyobj); - } -}; - -template <> struct Converter : Converter_PyFloat {}; -template <> struct Converter : Converter_PyFloat {}; - -// PyEnum Conversions --------------------------------------------------------- -template -struct EnumConverter -{ - static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType()); } - static inline bool isConvertible(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType()); } - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } - static inline PyObject* toPython(CppEnum cppenum) - { - return Shiboken::Enum::newItem(Shiboken::SbkType(), (long) cppenum); - } - static inline CppEnum toCpp(PyObject* pyObj) - { - return (CppEnum) Shiboken::Enum::getValue(pyObj);; - } -}; - -// C Sting Types -------------------------------------------------------------- -template -struct Converter_CString -{ - // Note: 0 is also a const char* in C++, so None is accepted in checkType - static inline bool checkType(PyObject* pyObj) { - return Shiboken::String::check(pyObj); - } - static inline bool isConvertible(PyObject* pyObj) { - return Shiboken::String::isConvertible(pyObj); - } - static inline PyObject* toPython(void* cppobj) { return toPython(reinterpret_cast(cppobj)); } - static inline PyObject* toPython(CString cppobj) - { - if (!cppobj) - Py_RETURN_NONE; - return Shiboken::String::fromCString(cppobj); - } - static inline CString toCpp(PyObject* pyobj) { - if (pyobj == Py_None) - return 0; - return Shiboken::String::toCString(pyobj); - } -}; - -template <> struct Converter : Converter_CString {}; - -template <> struct Converter : Converter_CString -{ - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } - static inline PyObject* toPython(std::string cppObj) - { - return Shiboken::String::fromCString(cppObj.c_str()); - } - - static inline std::string toCpp(PyObject* pyobj) - { - if (pyobj == Py_None) - return 0; - return std::string(Shiboken::String::toCString(pyobj)); - } -}; - -// C++ containers ------------------------------------------------------------- -// The following container converters are meant to be used for pairs, lists and maps -// that are similar to the STL containers of the same name. - -// For example to create a converter for a std::list the following code is enough: -// template struct Converter > : StdListConverter > {}; - -// And this for a std::map: -// template -// struct Converter > : StdMapConverter > {}; - -template -struct StdListConverter -{ - static inline bool checkType(PyObject* pyObj) - { - return isConvertible(pyObj); - } - - static inline bool isConvertible(PyObject* pyObj) - { - if (PyObject_TypeCheck(pyObj, SbkType())) - return true; - // Sequence conversion are made ONLY for python sequences, not for - // binded types implementing sequence protocol, otherwise this will - // cause a mess like QBitArray being accepted by someone expecting a - // QStringList. - if ((SbkType() && Object::checkType(pyObj)) || !PySequence_Check(pyObj)) - return false; - for (int i = 0, max = PySequence_Length(pyObj); i < max; ++i) { - AutoDecRef item(PySequence_GetItem(pyObj, i)); - if (!Converter::isConvertible(item)) - return false; - } - return true; - } - static PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast(cppObj)); } - static PyObject* toPython(const StdList& cppobj) - { - PyObject* result = PyList_New((int) cppobj.size()); - typename StdList::const_iterator it = cppobj.begin(); - for (int idx = 0; it != cppobj.end(); ++it, ++idx) { - typename StdList::value_type vh(*it); - PyList_SET_ITEM(result, idx, Converter::toPython(vh)); - } - return result; - } - static StdList toCpp(PyObject* pyobj) - { - if (PyObject_TypeCheck(pyobj, SbkType())) - return *reinterpret_cast(Object::cppPointer(reinterpret_cast(pyobj), SbkType())); - - StdList result; - for (int i = 0; i < PySequence_Size(pyobj); i++) { - AutoDecRef pyItem(PySequence_GetItem(pyobj, i)); - result.push_back(Converter::toCpp(pyItem)); - } - return result; - } -}; - -template -struct StdPairConverter -{ - static inline bool checkType(PyObject* pyObj) - { - return isConvertible(pyObj); - } - - static inline bool isConvertible(PyObject* pyObj) - { - if (PyObject_TypeCheck(pyObj, SbkType())) - return true; - if ((SbkType() && Object::checkType(pyObj)) || !PySequence_Check(pyObj) || PySequence_Length(pyObj) != 2) - return false; - - AutoDecRef item1(PySequence_GetItem(pyObj, 0)); - AutoDecRef item2(PySequence_GetItem(pyObj, 1)); - - if (!Converter::isConvertible(item1) - && !Converter::isConvertible(item2)) { - return false; - } - return true; - } - static PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast(cppObj)); } - static PyObject* toPython(const StdPair& cppobj) - { - typename StdPair::first_type first(cppobj.first); - typename StdPair::second_type second(cppobj.second); - PyObject* tuple = PyTuple_New(2); - PyTuple_SET_ITEM(tuple, 0, Converter::toPython(first)); - PyTuple_SET_ITEM(tuple, 1, Converter::toPython(second)); - return tuple; - } - static StdPair toCpp(PyObject* pyobj) - { - StdPair result; - AutoDecRef pyFirst(PySequence_GetItem(pyobj, 0)); - AutoDecRef pySecond(PySequence_GetItem(pyobj, 1)); - result.first = Converter::toCpp(pyFirst); - result.second = Converter::toCpp(pySecond); - return result; - } -}; - -template -struct StdMapConverter -{ - static inline bool checkType(PyObject* pyObj) - { - return isConvertible(pyObj); - } - - static inline bool isConvertible(PyObject* pyObj) - { - if (PyObject_TypeCheck(pyObj, SbkType())) - return true; - if ((SbkType() && Object::checkType(pyObj)) || !PyDict_Check(pyObj)) - return false; - - PyObject* key; - PyObject* value; - Py_ssize_t pos = 0; - - while (PyDict_Next(pyObj, &pos, &key, &value)) { - if (!Converter::isConvertible(key) - || !Converter::isConvertible(value)) { - return false; - } - } - return true; - } - - static PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast(cppObj)); } - static PyObject* toPython(const StdMap& cppobj) - { - PyObject* result = PyDict_New(); - typename StdMap::const_iterator it = cppobj.begin(); - - for (; it != cppobj.end(); ++it) { - PyDict_SetItem(result, - Converter::toPython(it->first), - Converter::toPython(it->second)); - } - - return result; - } - static StdMap toCpp(PyObject* pyobj) - { - StdMap result; - - PyObject* key; - PyObject* value; - Py_ssize_t pos = 0; - - while (PyDict_Next(pyobj, &pos, &key, &value)) { - result.insert(typename StdMap::value_type( - Converter::toCpp(key), - Converter::toCpp(value))); - } - return result; - } -}; - - -// class used to translate python objects to another type -template struct PythonConverter {}; - -} // namespace Shiboken - -#endif // CONVERSIONS_H - diff --git a/sources/shiboken2/libshiboken/helper.cpp b/sources/shiboken2/libshiboken/helper.cpp index 5792db5be..3ef68502b 100644 --- a/sources/shiboken2/libshiboken/helper.cpp +++ b/sources/shiboken2/libshiboken/helper.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "helper.h" +#include "sbkstring.h" #include namespace Shiboken diff --git a/sources/shiboken2/libshiboken/helper.h b/sources/shiboken2/libshiboken/helper.h index 33d97c62c..f3b50a7ea 100644 --- a/sources/shiboken2/libshiboken/helper.h +++ b/sources/shiboken2/libshiboken/helper.h @@ -42,7 +42,6 @@ #include "sbkpython.h" #include "shibokenmacros.h" -#include "conversions.h" #include "autodecref.h" #define SBK_UNUSED(x) (void)x; @@ -50,46 +49,6 @@ namespace Shiboken { -template -inline PyObject* makeTuple(const A& a) -{ - return PyTuple_Pack(1, AutoDecRef(Converter::toPython(a)).object()); -} - -template -inline PyObject* makeTuple(const A& a, const B& b) -{ - return PyTuple_Pack(2, AutoDecRef(Converter::toPython(a)).object(), - AutoDecRef(Converter::toPython(b)).object()); -} - -template -inline PyObject* makeTuple(const A& a, const B& b, const C& c) -{ - return PyTuple_Pack(3, AutoDecRef(Converter::toPython(a)).object(), - AutoDecRef(Converter::toPython(b)).object(), - AutoDecRef(Converter::toPython(c)).object()); -} - -template -inline PyObject* makeTuple(const A& a, const B& b, const C& c, const D& d) -{ - return PyTuple_Pack(4, AutoDecRef(Converter::toPython(a)).object(), - AutoDecRef(Converter::toPython(b)).object(), - AutoDecRef(Converter::toPython(c)).object(), - AutoDecRef(Converter::toPython(d)).object()); -} - -template -inline PyObject* makeTuple(const A& a, const B& b, const C& c, const D& d, const E& e) -{ - return PyTuple_Pack(5, AutoDecRef(Converter::toPython(a)).object(), - AutoDecRef(Converter::toPython(b)).object(), - AutoDecRef(Converter::toPython(c)).object(), - AutoDecRef(Converter::toPython(d)).object(), - AutoDecRef(Converter::toPython(e)).object()); -} - /** * It transforms a python sequence into two C variables, argc and argv. * This function tries to find the application (script) name and put it into argv[0], if diff --git a/sources/shiboken2/libshiboken/sbkconverter.cpp b/sources/shiboken2/libshiboken/sbkconverter.cpp index 0b18e49d4..ebd586a5e 100644 --- a/sources/shiboken2/libshiboken/sbkconverter.cpp +++ b/sources/shiboken2/libshiboken/sbkconverter.cpp @@ -40,6 +40,7 @@ #include "sbkconverter.h" #include "sbkconverter_p.h" #include "basewrapper_p.h" +#include "bindingmanager.h" #include "google/dense_hash_map" #include "autodecref.h" #include "sbkdbg.h" diff --git a/sources/shiboken2/libshiboken/sbkconverter.h b/sources/shiboken2/libshiboken/sbkconverter.h index 7489b930d..7eb666b25 100644 --- a/sources/shiboken2/libshiboken/sbkconverter.h +++ b/sources/shiboken2/libshiboken/sbkconverter.h @@ -358,7 +358,38 @@ template<> inline SbkConverter* PrimitiveTypeConverter() { return template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_UNSIGNEDSHORT_IDX); } template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_VOIDPTR_IDX); } -} } // namespace Shiboken::Conversions +} // namespace Shiboken::Conversions + +/** +* This function template is used to get the PyTypeObject of a C++ type T. +* All implementations should be provided by template specializations generated by the generator when +* T isn't a C++ primitive type. +* \see SpecialCastFunction +*/ +template PyTypeObject* SbkType() { return 0; } + +// Below are the template specializations for C++ primitive types. +template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } +template<> inline PyTypeObject* SbkType() { return &PyBool_Type; } +template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } +template<> inline PyTypeObject* SbkType() { return &PyFloat_Type; } +template<> inline PyTypeObject* SbkType() { return &PyFloat_Type; } +template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } +template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } +template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } +template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } +template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } +template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } +template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } +template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } +template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } + +} // namespace Shiboken + +// When the user adds a function with an argument unknown for the typesystem, the generator writes type checks as +// TYPENAME_Check, so this macro allows users to add PyObject arguments to their added functions. +#define PyObject_Check(X) true +#define SbkChar_Check(X) (SbkNumber_Check(X) || Shiboken::String::checkChar(X)) struct _SbkGenericType { PyHeapTypeObject super; SbkConverter** converter; }; #define SBK_CONVERTER(pyType) (*reinterpret_cast<_SbkGenericType*>(pyType)->converter) diff --git a/sources/shiboken2/libshiboken/sbkconverter_p.h b/sources/shiboken2/libshiboken/sbkconverter_p.h index b38561780..7efccbab4 100644 --- a/sources/shiboken2/libshiboken/sbkconverter_p.h +++ b/sources/shiboken2/libshiboken/sbkconverter_p.h @@ -215,22 +215,6 @@ struct OverFlowChecker : }; // Basic primitive type converters --------------------------------------------------------- -template PyTypeObject* SbkType() { return 0; } -template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType() { return &PyBool_Type; } -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType() { return &PyString_Type; } -template<> inline PyTypeObject* SbkType() { return &PyFloat_Type; } -template<> inline PyTypeObject* SbkType() { return &PyFloat_Type; } -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } template struct Primitive {}; @@ -242,8 +226,11 @@ struct OnePrimitive static void toCpp(PyObject*, void*) {} static SbkConverter* createConverter() { - SbkConverter* converter = Shiboken::Conversions::createConverter(SbkType(), Primitive::toPython); - Shiboken::Conversions::addPythonToCppValueConversion(converter, Primitive::toCpp, Primitive::isConvertible); + SbkConverter* converter = Shiboken::Conversions::createConverter(Shiboken::SbkType(), + Primitive::toPython); + Shiboken::Conversions::addPythonToCppValueConversion(converter, + Primitive::toCpp, + Primitive::isConvertible); return converter; } }; diff --git a/sources/shiboken2/libshiboken/sbkenum.cpp b/sources/shiboken2/libshiboken/sbkenum.cpp index 009d9ab2f..a62448aa6 100644 --- a/sources/shiboken2/libshiboken/sbkenum.cpp +++ b/sources/shiboken2/libshiboken/sbkenum.cpp @@ -43,7 +43,6 @@ #include "basewrapper.h" #include "sbkdbg.h" #include "autodecref.h" -#include "typeresolver.h" #include "sbkpython.h" #include @@ -444,17 +443,12 @@ static PyTypeObject* createEnum(const char* fullName, const char* cppName, const enumType->tp_as_number = flagsType->tp_as_number; if (PyType_Ready(enumType) < 0) return 0; - Shiboken::TypeResolver::createValueTypeResolver(cppName); - if (shortName) - Shiboken::TypeResolver::createValueTypeResolver(shortName); return enumType; } PyTypeObject* createGlobalEnum(PyObject* module, const char* name, const char* fullName, const char* cppName, PyTypeObject* flagsType) { PyTypeObject* enumType = createEnum(fullName, cppName, name, flagsType); - Shiboken::TypeResolver::createValueTypeResolver("Qt::WindowType"); - Shiboken::TypeResolver::createValueTypeResolver("WindowType"); if (enumType && PyModule_AddObject(module, name, reinterpret_cast(enumType)) < 0) return 0; if (flagsType && PyModule_AddObject(module, flagsType->tp_name, reinterpret_cast(flagsType)) < 0) diff --git a/sources/shiboken2/libshiboken/shiboken.h b/sources/shiboken2/libshiboken/shiboken.h index 2738bf51f..9f4b8a560 100644 --- a/sources/shiboken2/libshiboken/shiboken.h +++ b/sources/shiboken2/libshiboken/shiboken.h @@ -44,7 +44,6 @@ #include "autodecref.h" #include "basewrapper.h" #include "bindingmanager.h" -#include "conversions.h" #include "gilstate.h" #include "threadstatesaver.h" #include "helper.h" @@ -53,7 +52,6 @@ #include "sbkmodule.h" #include "sbkstring.h" #include "shibokenmacros.h" -#include "typeresolver.h" #include "shibokenbuffer.h" #endif // SHIBOKEN_H diff --git a/sources/shiboken2/libshiboken/typeresolver.cpp b/sources/shiboken2/libshiboken/typeresolver.cpp deleted file mode 100644 index 3939fff5f..000000000 --- a/sources/shiboken2/libshiboken/typeresolver.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "typeresolver.h" -#include "google/dense_hash_map" -#include "sbkdbg.h" -#include -#include -#include "basewrapper_p.h" - -using namespace Shiboken; - -typedef google::dense_hash_map TypeResolverMap; -static TypeResolverMap typeResolverMap; - -struct TypeResolver::TypeResolverPrivate -{ - CppToPythonFunc cppToPython; - PythonToCppFunc pythonToCpp; - PyTypeObject* pyType; -}; - -static void deinitTypeResolver() -{ - for (TypeResolverMap::const_iterator it = typeResolverMap.begin(); it != typeResolverMap.end(); ++it) - delete it->second; - typeResolverMap.clear(); -} - -void Shiboken::initTypeResolver() -{ - assert(typeResolverMap.empty()); - typeResolverMap.set_empty_key(""); - typeResolverMap.set_deleted_key("?"); - std::atexit(deinitTypeResolver); -} - -TypeResolver::TypeResolver() : m_d(new TypeResolverPrivate) -{ -} - -TypeResolver* TypeResolver::createTypeResolver(const char* typeName, - CppToPythonFunc cppToPy, - PythonToCppFunc pyToCpp, - PyTypeObject* pyType) -{ - TypeResolver*& tr = typeResolverMap[typeName]; - if (!tr) { - tr = new TypeResolver; - tr->m_d->cppToPython = cppToPy; - tr->m_d->pythonToCpp = pyToCpp; - tr->m_d->pyType = pyType; - - /* - * Note: - * - * Value types are also registered as object types, but the generator *always* first register the value - * type version in the TypeResolver and it *must* always do it! otherwise this code wont work. - */ - if (pyType && PyType_IsSubtype(pyType, reinterpret_cast(&SbkObject_Type))) { - SbkObjectType* sbkType = reinterpret_cast(pyType); - // TODO-CONVERTERS: to be deprecated - if (!sbkType->d->type_behaviour) { - const size_t len = strlen(typeName); - sbkType->d->type_behaviour = typeName[len -1] == '*' ? BEHAVIOUR_OBJECTTYPE : BEHAVIOUR_VALUETYPE; - } - } - } - return tr; -} - -TypeResolver::~TypeResolver() -{ - delete m_d; -} - -TypeResolver* TypeResolver::get(const char* typeName) -{ - TypeResolverMap::const_iterator it = typeResolverMap.find(typeName); - if (it != typeResolverMap.end()) { - return it->second; - } else { - if (Py_VerboseFlag > 0) - SbkDbg() << "Can't find type resolver for " << typeName; - return 0; - } -} - -void TypeResolver::toCpp(PyObject* pyObj, void** place) -{ - m_d->pythonToCpp(pyObj, place); -} - -PyObject* TypeResolver::toPython(void* cppObj) -{ - return m_d->cppToPython(cppObj); -} - -PyTypeObject* TypeResolver::pythonType() -{ - return m_d->pyType; -} - -TypeResolver::Type TypeResolver::getType(const char* name) -{ - const size_t len = strlen(name); - bool isObjTypeName = name[len - 1] == '*'; - if (TypeResolver::get(name)) { - // great, we found the type in our first attempt! - return isObjTypeName ? ObjectType : ValueType; - } else { - // Type not found... let's copy the string. - std::string typeName(name); - if (isObjTypeName) - typeName.erase(len - 1, 1); - else - typeName += '*'; - isObjTypeName = !isObjTypeName; - - if (TypeResolver::get(typeName.c_str())) - return isObjTypeName ? ObjectType : ValueType; - else - return UnknownType; - } -} - diff --git a/sources/shiboken2/libshiboken/typeresolver.h b/sources/shiboken2/libshiboken/typeresolver.h deleted file mode 100644 index bc56522fe..000000000 --- a/sources/shiboken2/libshiboken/typeresolver.h +++ /dev/null @@ -1,139 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TYPERESOLVER_H -#define TYPERESOLVER_H - -#include "shibokenmacros.h" -#include "conversions.h" - -namespace Shiboken -{ - -/* To C++ convertion functions. */ -template -inline void pythonToValueType(PyObject* pyobj, void** data) -{ - *reinterpret_cast(*data) = Shiboken::Converter::toCpp(pyobj); -} - -template -inline void pythonToObjectType(PyObject* pyobj, void** data) -{ - *reinterpret_cast(*data) = Shiboken::Converter::toCpp(pyobj); -} - -template -inline PyObject* objectTypeToPython(void* cptr) -{ - return Shiboken::Converter::toPython(*reinterpret_cast(cptr)); -} - -template -inline PyObject* referenceTypeToPython(void* cptr) -{ - // cptr comes the same way it come when we have a value type, but - // we deliver a Python object of a reference - return Shiboken::Converter::toPython(*reinterpret_cast(cptr)); -} - -/** -* \internal This function is not part of the public API. -* Initialize the TypeResource internal cache. -*/ -void initTypeResolver(); - -class LIBSHIBOKEN_API TypeResolver -{ -public: - enum Type - { - ObjectType, - ValueType, - UnknownType - }; - - typedef PyObject* (*CppToPythonFunc)(void*); - typedef void (*PythonToCppFunc)(PyObject*, void**); - - ~TypeResolver(); - - template - static TypeResolver* createValueTypeResolver(const char* typeName) - { - return createTypeResolver(typeName, &Shiboken::Converter::toPython, &pythonToValueType, SbkType()); - } - - template - static TypeResolver* createObjectTypeResolver(const char* typeName) - { - return createTypeResolver(typeName, &objectTypeToPython, &pythonToObjectType, SbkType()); - } - - /** - * This kind of type resolver is used only when we have a signal with a reference in their arguments - * like on QSqlTableModel::primeInsert. - */ - template - static TypeResolver* createReferenceTypeResolver(const char* typeName) - { - return createTypeResolver(typeName, &referenceTypeToPython, &pythonToValueType, SbkType()); - } - - static Type getType(const char* name); - static TypeResolver* get(const char* typeName); - - PyObject* toPython(void* cppObj); - void toCpp(PyObject* pyObj, void** place); - PyTypeObject* pythonType(); - -private: - struct TypeResolverPrivate; - TypeResolverPrivate* m_d; - - TypeResolver(); - // disable object copy - TypeResolver(const TypeResolver&); - TypeResolver& operator=(const TypeResolver&); - - static TypeResolver* createTypeResolver(const char* typeName, CppToPythonFunc cppToPy, PythonToCppFunc pyToCpp, PyTypeObject* pyType); -}; -} - -#endif -- cgit v1.2.3