diff options
Diffstat (limited to 'sources/shiboken2/libshiboken')
-rw-r--r-- | sources/shiboken2/libshiboken/CMakeLists.txt | 3 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/basewrapper.cpp | 4 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/conversions.h | 731 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/helper.cpp | 1 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/helper.h | 41 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/sbkconverter.cpp | 1 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/sbkconverter.h | 33 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/sbkconverter_p.h | 23 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/sbkenum.cpp | 6 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/shiboken.h | 2 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/typeresolver.cpp | 162 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/typeresolver.h | 139 |
12 files changed, 41 insertions, 1105 deletions
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 <string> #include <cstring> @@ -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 <limits> -#include <typeinfo> - -#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<typename T> -PyTypeObject* SbkType() -{ - return 0; -} - -template<> inline PyTypeObject* SbkType<int>() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType<unsigned int>() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType<short>() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType<unsigned short>() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType<long>() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType<unsigned long>() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType<PY_LONG_LONG>() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType<unsigned PY_LONG_LONG>() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType<bool>() { return &PyBool_Type; } -template<> inline PyTypeObject* SbkType<float>() { return &PyFloat_Type; } -template<> inline PyTypeObject* SbkType<double>() { return &PyFloat_Type; } -template<> inline PyTypeObject* SbkType<char>() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType<signed char>() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType<unsigned char>() { return &PyInt_Type; } - -/** - * Convenience template to create wrappers using the proper Python type for a given C++ class instance. - */ -template<typename T> -inline PyObject* createWrapper(const T* cppobj, bool hasOwnership = false, bool isExactType = false) -{ - const char* typeName = 0; - if (!isExactType) - typeName = typeid(*const_cast<T*>(cppobj)).name(); - return Object::newObject(reinterpret_cast<SbkObjectType*>(SbkType<T>()), - const_cast<T*>(cppobj), hasOwnership, isExactType, typeName); -} - -// Base Conversions ---------------------------------------------------------- -// The basic converter must be empty to avoid object types being converted by value. -template <typename T> struct Converter {}; - -// Pointer conversion specialization for value types. -template <typename T> -struct Converter<T*> -{ - static inline bool checkType(PyObject* pyObj) - { - return Converter<T>::checkType(pyObj); - } - - static inline bool isConvertible(PyObject* pyObj) - { - return pyObj == Py_None || PyObject_TypeCheck(pyObj, SbkType<T>()); - } - - static PyObject* toPython(const T* cppobj) - { - if (!cppobj) - Py_RETURN_NONE; - PyObject* pyobj = reinterpret_cast<PyObject*>(BindingManager::instance().retrieveWrapper(cppobj)); - if (pyobj) - Py_INCREF(pyobj); - else - pyobj = createWrapper<T>(cppobj); - return pyobj; - } - - static T* toCpp(PyObject* pyobj) - { - if (PyObject_TypeCheck(pyobj, SbkType<T>())) - return reinterpret_cast<T *>(Object::cppPointer(reinterpret_cast<SbkObject *>(pyobj), SbkType<T>())); - else if (Converter<T>::isConvertible(pyobj)) - return new T(Converter<T>::toCpp(pyobj)); - else if (pyobj == Py_None) - return 0; - - assert(false); - return 0; - } -}; -template <typename T> struct Converter<const T*> : Converter<T*> {}; - -// Specialization for reference conversions. -template <typename T> -struct Converter<T&> -{ - static inline bool checkType(PyObject* pyObj) { return Converter<T>::checkType(pyObj); } - static inline bool isConvertible(PyObject* pyObj) { return Converter<T>::isConvertible(pyObj); } - static inline PyObject* toPython(const T& cppobj) { return Converter<T*>::toPython(&cppobj); } - static inline T& toCpp(PyObject* pyobj) { return *Converter<T*>::toCpp(pyobj); } -}; - -// Void pointer conversions. -template<> -struct Converter<void*> -{ - 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<PyObject *>(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<ValueTypeClass> : ValueTypeConverter<ValueTypeClass>" -template <typename T> -struct ValueTypeConverter -{ - static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType<T>()); } - - // 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<T>())) - return true; - SbkObjectType* shiboType = reinterpret_cast<SbkObjectType*>(SbkType<T>()); - return ObjectType::isExternalConvertible(shiboType, pyobj); - } - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<T*>(cppobj)); } - static inline PyObject* toPython(const T& cppobj) - { - PyObject* obj = createWrapper<T>(new T(cppobj), true, true); -// SbkBaseWrapper_setContainsCppWrapper(obj, SbkTypeInfo<T>::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<T>())) { - SbkObjectType* shiboType = reinterpret_cast<SbkObjectType*>(SbkType<T>()); - if (ObjectType::hasExternalCppConversions(shiboType) && isConvertible(pyobj)) { - T* cptr = reinterpret_cast<T*>(ObjectType::callExternalCppConversion(shiboType, pyobj)); - const T result = *cptr; - delete cptr; - return result; - } - assert(false); - } - return *reinterpret_cast<T*>(Object::cppPointer(reinterpret_cast<SbkObject*>(pyobj), SbkType<T>())); - } -}; - -// 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<AbstractClass*> : ObjectTypeConverter<AbstractClass>" -template <typename T> -struct ObjectTypeConverter -{ - static inline bool checkType(PyObject* pyObj) { return pyObj == Py_None || PyObject_TypeCheck(pyObj, SbkType<T>()); } - /// 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<T>()); } - /// Convenience overload that calls "toPython(const T*)" method. - static inline PyObject* toPython(void* cppobj) { return toPython(reinterpret_cast<T*>(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<PyObject*>(BindingManager::instance().retrieveWrapper(cppobj)); - if (pyobj) - Py_INCREF(pyobj); - else - pyobj = createWrapper<T>(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<SbkObject *>(pyobj); - SbkObjectType* shiboType = reinterpret_cast<SbkObjectType*>(pyobj->ob_type); - if (ObjectType::hasCast(shiboType)) - return reinterpret_cast<T*>(ObjectType::cast(shiboType, sbkObj, SbkType<T>())); - return reinterpret_cast<T *>(Object::cppPointer(sbkObj, SbkType<T>())); - } -}; - -template <typename T> -struct ObjectTypeReferenceConverter : ObjectTypeConverter<T> -{ - static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType<T>()); } - static inline bool isConvertible(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType<T>()); } - static inline PyObject* toPython(const T& cppobj) { return Converter<T*>::toPython(&cppobj); } - static inline T& toCpp(PyObject* pyobj) - { - T* t = Converter<T*>::toCpp(pyobj); - assert(t); - return *t; - } -}; - -// PyObject* specialization to avoid converting what doesn't need to be converted. -template<> -struct Converter<PyObject*> : ObjectTypeConverter<PyObject*> -{ - static inline PyObject* toCpp(PyObject* pyobj) { return pyobj; } -}; - -// Primitive Conversions ------------------------------------------------------ -template <> -struct Converter<bool> -{ - 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<bool*>(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<typename T, bool isSigned = std::numeric_limits<T>::is_signed > -struct OverFlowChecker; - -template<typename T> -struct OverFlowChecker<T, true> -{ - static bool check(const PY_LONG_LONG& value) - { - return value < std::numeric_limits<T>::min() || value > std::numeric_limits<T>::max(); - } -}; - -template<typename T> -struct OverFlowChecker<T, false> -{ - static bool check(const PY_LONG_LONG& value) - { - return value < 0 || static_cast<unsigned long long>(value) > std::numeric_limits<T>::max(); - } -}; - -template<> -struct OverFlowChecker<PY_LONG_LONG, true> -{ - static bool check(const PY_LONG_LONG &) - { - return false; - } -}; - -template<> -struct OverFlowChecker<double, true> -{ - static bool check(const double &) - { - return false; - } -}; - -template<> -struct OverFlowChecker<float, true> -{ - static bool check(const double& value) - { - return value < std::numeric_limits<float>::min() || value > std::numeric_limits<float>::max(); - } -}; - -template <typename PyIntEquiv> -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<PyIntEquiv*>(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<PyIntEquiv>::check(d_result)) - PyErr_SetObject(PyExc_OverflowError, 0); - return static_cast<PyIntEquiv>(d_result); - } else { - PY_LONG_LONG result = PyLong_AsLongLong(pyobj); - if (OverFlowChecker<PyIntEquiv>::check(result)) - PyErr_SetObject(PyExc_OverflowError, 0); - return static_cast<PyIntEquiv>(result); - } - } -}; - -template <typename T> -struct Converter_PyULongInt : Converter_PyInt<T> -{ - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<T*>(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 <typename CharType> -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<CharType*>(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<CharType>::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<unsigned long> : Converter_PyULongInt<unsigned long> {}; -template <> struct Converter<unsigned int> : Converter_PyULongInt<unsigned int> {}; -template <> struct Converter<char> : CharConverter<char> -{ - // Should we really return a string? - using CharConverter<char>::toPython; - using CharConverter<char>::isConvertible; - using CharConverter<char>::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<char>::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<signed char> : CharConverter<signed char> {}; -template <> struct Converter<unsigned char> : CharConverter<unsigned char> {}; -template <> struct Converter<int> : Converter_PyInt<int> {}; -template <> struct Converter<short> : Converter_PyInt<short> {}; -template <> struct Converter<unsigned short> : Converter_PyInt<unsigned short> {}; -template <> struct Converter<long> : Converter_PyInt<long> {}; - -template <> -struct Converter<PY_LONG_LONG> -{ - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<PY_LONG_LONG*>(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<unsigned PY_LONG_LONG> -{ - static inline PyObject* toPython(void* cppobj) - { - return toPython(*reinterpret_cast<unsigned PY_LONG_LONG*>(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 <typename PyFloatEquiv> -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<PyFloatEquiv*>(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<float> : Converter_PyFloat<float> {}; -template <> struct Converter<double> : Converter_PyFloat<double> {}; - -// PyEnum Conversions --------------------------------------------------------- -template <typename CppEnum> -struct EnumConverter -{ - static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType<CppEnum>()); } - static inline bool isConvertible(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType<CppEnum>()); } - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<CppEnum*>(cppobj)); } - static inline PyObject* toPython(CppEnum cppenum) - { - return Shiboken::Enum::newItem(Shiboken::SbkType<CppEnum>(), (long) cppenum); - } - static inline CppEnum toCpp(PyObject* pyObj) - { - return (CppEnum) Shiboken::Enum::getValue(pyObj);; - } -}; - -// C Sting Types -------------------------------------------------------------- -template <typename CString> -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<CString>(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<const char*> : Converter_CString<const char*> {}; - -template <> struct Converter<std::string> : Converter_CString<std::string> -{ - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<std::string*>(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<typename T> struct Converter<std::list<T> > : StdListConverter<std::list<T> > {}; - -// And this for a std::map: -// template<typename KT, typename VT> -// struct Converter<std::map<KT, VT> > : StdMapConverter<std::map<KT, VT> > {}; - -template <typename StdList> -struct StdListConverter -{ - static inline bool checkType(PyObject* pyObj) - { - return isConvertible(pyObj); - } - - static inline bool isConvertible(PyObject* pyObj) - { - if (PyObject_TypeCheck(pyObj, SbkType<StdList>())) - 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<StdList>() && 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<typename StdList::value_type>::isConvertible(item)) - return false; - } - return true; - } - static PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast<StdList*>(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<typename StdList::value_type>::toPython(vh)); - } - return result; - } - static StdList toCpp(PyObject* pyobj) - { - if (PyObject_TypeCheck(pyobj, SbkType<StdList>())) - return *reinterpret_cast<StdList*>(Object::cppPointer(reinterpret_cast<SbkObject*>(pyobj), SbkType<StdList>())); - - StdList result; - for (int i = 0; i < PySequence_Size(pyobj); i++) { - AutoDecRef pyItem(PySequence_GetItem(pyobj, i)); - result.push_back(Converter<typename StdList::value_type>::toCpp(pyItem)); - } - return result; - } -}; - -template <typename StdPair> -struct StdPairConverter -{ - static inline bool checkType(PyObject* pyObj) - { - return isConvertible(pyObj); - } - - static inline bool isConvertible(PyObject* pyObj) - { - if (PyObject_TypeCheck(pyObj, SbkType<StdPair>())) - return true; - if ((SbkType<StdPair>() && 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<typename StdPair::first_type>::isConvertible(item1) - && !Converter<typename StdPair::second_type>::isConvertible(item2)) { - return false; - } - return true; - } - static PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast<StdPair*>(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<typename StdPair::first_type>::toPython(first)); - PyTuple_SET_ITEM(tuple, 1, Converter<typename StdPair::second_type>::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<typename StdPair::first_type>::toCpp(pyFirst); - result.second = Converter<typename StdPair::second_type>::toCpp(pySecond); - return result; - } -}; - -template <typename StdMap> -struct StdMapConverter -{ - static inline bool checkType(PyObject* pyObj) - { - return isConvertible(pyObj); - } - - static inline bool isConvertible(PyObject* pyObj) - { - if (PyObject_TypeCheck(pyObj, SbkType<StdMap>())) - return true; - if ((SbkType<StdMap>() && 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<typename StdMap::key_type>::isConvertible(key) - || !Converter<typename StdMap::mapped_type>::isConvertible(value)) { - return false; - } - } - return true; - } - - static PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast<StdMap*>(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<typename StdMap::key_type>::toPython(it->first), - Converter<typename StdMap::mapped_type>::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<typename StdMap::key_type>::toCpp(key), - Converter<typename StdMap::mapped_type>::toCpp(value))); - } - return result; - } -}; - - -// class used to translate python objects to another type -template <typename T> 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 <stdarg.h> 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<typename A> -inline PyObject* makeTuple(const A& a) -{ - return PyTuple_Pack(1, AutoDecRef(Converter<A>::toPython(a)).object()); -} - -template<typename A, typename B> -inline PyObject* makeTuple(const A& a, const B& b) -{ - return PyTuple_Pack(2, AutoDecRef(Converter<A>::toPython(a)).object(), - AutoDecRef(Converter<B>::toPython(b)).object()); -} - -template<typename A, typename B, typename C> -inline PyObject* makeTuple(const A& a, const B& b, const C& c) -{ - return PyTuple_Pack(3, AutoDecRef(Converter<A>::toPython(a)).object(), - AutoDecRef(Converter<B>::toPython(b)).object(), - AutoDecRef(Converter<C>::toPython(c)).object()); -} - -template<typename A, typename B, typename C, typename D> -inline PyObject* makeTuple(const A& a, const B& b, const C& c, const D& d) -{ - return PyTuple_Pack(4, AutoDecRef(Converter<A>::toPython(a)).object(), - AutoDecRef(Converter<B>::toPython(b)).object(), - AutoDecRef(Converter<C>::toPython(c)).object(), - AutoDecRef(Converter<D>::toPython(d)).object()); -} - -template<typename A, typename B, typename C, typename D, typename E> -inline PyObject* makeTuple(const A& a, const B& b, const C& c, const D& d, const E& e) -{ - return PyTuple_Pack(5, AutoDecRef(Converter<A>::toPython(a)).object(), - AutoDecRef(Converter<B>::toPython(b)).object(), - AutoDecRef(Converter<C>::toPython(c)).object(), - AutoDecRef(Converter<D>::toPython(d)).object(), - AutoDecRef(Converter<E>::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<unsigned long>() { return template<> inline SbkConverter* PrimitiveTypeConverter<unsigned short>() { return primitiveTypeConverter(SBK_UNSIGNEDSHORT_IDX); } template<> inline SbkConverter* PrimitiveTypeConverter<void*>() { 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<typename T> PyTypeObject* SbkType() { return 0; } + +// Below are the template specializations for C++ primitive types. +template<> inline PyTypeObject* SbkType<PY_LONG_LONG>() { return &PyLong_Type; } +template<> inline PyTypeObject* SbkType<bool>() { return &PyBool_Type; } +template<> inline PyTypeObject* SbkType<char>() { return &PyInt_Type; } +template<> inline PyTypeObject* SbkType<double>() { return &PyFloat_Type; } +template<> inline PyTypeObject* SbkType<float>() { return &PyFloat_Type; } +template<> inline PyTypeObject* SbkType<int>() { return &PyInt_Type; } +template<> inline PyTypeObject* SbkType<long>() { return &PyLong_Type; } +template<> inline PyTypeObject* SbkType<short>() { return &PyInt_Type; } +template<> inline PyTypeObject* SbkType<signed char>() { return &PyInt_Type; } +template<> inline PyTypeObject* SbkType<unsigned PY_LONG_LONG>() { return &PyLong_Type; } +template<> inline PyTypeObject* SbkType<unsigned char>() { return &PyInt_Type; } +template<> inline PyTypeObject* SbkType<unsigned int>() { return &PyLong_Type; } +template<> inline PyTypeObject* SbkType<unsigned long>() { return &PyLong_Type; } +template<> inline PyTypeObject* SbkType<unsigned short>() { 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<float, PY_LONG_LONG, true> : }; // Basic primitive type converters --------------------------------------------------------- -template<typename T> PyTypeObject* SbkType() { return 0; } -template<> inline PyTypeObject* SbkType<PY_LONG_LONG>() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType<bool>() { return &PyBool_Type; } -template<> inline PyTypeObject* SbkType<char>() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType<const char*>() { return &PyString_Type; } -template<> inline PyTypeObject* SbkType<double>() { return &PyFloat_Type; } -template<> inline PyTypeObject* SbkType<float>() { return &PyFloat_Type; } -template<> inline PyTypeObject* SbkType<int>() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType<long>() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType<short>() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType<signed char>() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType<unsigned PY_LONG_LONG>() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType<unsigned char>() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType<unsigned int>() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType<unsigned long>() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType<unsigned short>() { return &PyInt_Type; } template <typename T> struct Primitive {}; @@ -242,8 +226,11 @@ struct OnePrimitive static void toCpp(PyObject*, void*) {} static SbkConverter* createConverter() { - SbkConverter* converter = Shiboken::Conversions::createConverter(SbkType<T>(), Primitive<T>::toPython); - Shiboken::Conversions::addPythonToCppValueConversion(converter, Primitive<T>::toCpp, Primitive<T>::isConvertible); + SbkConverter* converter = Shiboken::Conversions::createConverter(Shiboken::SbkType<T>(), + Primitive<T>::toPython); + Shiboken::Conversions::addPythonToCppValueConversion(converter, + Primitive<T>::toCpp, + Primitive<T>::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 <string.h> @@ -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<int>(cppName); - if (shortName) - Shiboken::TypeResolver::createValueTypeResolver<int>(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<int>("Qt::WindowType"); - Shiboken::TypeResolver::createValueTypeResolver<int>("WindowType"); if (enumType && PyModule_AddObject(module, name, reinterpret_cast<PyObject *>(enumType)) < 0) return 0; if (flagsType && PyModule_AddObject(module, flagsType->tp_name, reinterpret_cast<PyObject *>(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 <cstdlib> -#include <string> -#include "basewrapper_p.h" - -using namespace Shiboken; - -typedef google::dense_hash_map<std::string, TypeResolver*> 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<PyTypeObject*>(&SbkObject_Type))) { - SbkObjectType* sbkType = reinterpret_cast<SbkObjectType*>(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 <typename T> -inline void pythonToValueType(PyObject* pyobj, void** data) -{ - *reinterpret_cast<T*>(*data) = Shiboken::Converter<T>::toCpp(pyobj); -} - -template <typename T> -inline void pythonToObjectType(PyObject* pyobj, void** data) -{ - *reinterpret_cast<T**>(*data) = Shiboken::Converter<T*>::toCpp(pyobj); -} - -template <typename T> -inline PyObject* objectTypeToPython(void* cptr) -{ - return Shiboken::Converter<T*>::toPython(*reinterpret_cast<T**>(cptr)); -} - -template <typename T> -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<T&>::toPython(*reinterpret_cast<T*>(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<typename T> - static TypeResolver* createValueTypeResolver(const char* typeName) - { - return createTypeResolver(typeName, &Shiboken::Converter<T>::toPython, &pythonToValueType<T>, SbkType<T>()); - } - - template<typename T> - static TypeResolver* createObjectTypeResolver(const char* typeName) - { - return createTypeResolver(typeName, &objectTypeToPython<T>, &pythonToObjectType<T>, SbkType<T>()); - } - - /** - * This kind of type resolver is used only when we have a signal with a reference in their arguments - * like on QSqlTableModel::primeInsert. - */ - template<typename T> - static TypeResolver* createReferenceTypeResolver(const char* typeName) - { - return createTypeResolver(typeName, &referenceTypeToPython<T>, &pythonToValueType<T>, SbkType<T>()); - } - - 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 |