/* * This file is part of the Shiboken Python Bindings Generator project. * * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: PySide team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. Please * review the following information to ensure the GNU Lesser General * Public License version 2.1 requirements will be met: * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * As a special exception to the GNU Lesser General Public License * version 2.1, the object code form of a "work that uses the Library" * may incorporate material from a header file that is part of the * Library. You may distribute such object code under terms of your * choice, provided that the incorporated material (i) does not exceed * more than 5% of the total size of the Library; and (ii) is limited to * numerical parameters, data structure layouts, accessors, macros, * inline functions and templates. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef CONVERSIONS_H #define CONVERSIONS_H #include #include #include #include "pyenum.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 #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; } template struct SbkTypeInfo { static const bool isCppWrapper = false; }; /** * This struct template is used to copy a C++ object using the proper * constructor, which could be the same type as used on the wrapped library * or a C++ wrapper type provided by the binding. */ template ::isCppWrapper> struct CppObjectCopier { static inline T* copy(const T& obj); }; template struct CppObjectCopier { static inline T* copy(const T& obj) { return new T(*reinterpret_cast(&obj)); } }; template struct CppObjectCopier { static inline T* copy(const T& obj) { return reinterpret_cast(reinterpret_cast(SbkType())->obj_copier(&obj)); } }; /** * 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) { return SbkBaseWrapper_New(reinterpret_cast(SbkType()), cppobj, hasOwnership, isExactType); } // 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 isConvertible(PyObject* pyObj) { return pyObj == Py_None || PyObject_TypeCheck(pyObj, SbkType()); } static PyObject* toPython(const T* cppobj) { if (!cppobj) Py_RETURN_NONE; PyObject* pyobj = BindingManager::instance().retrieveWrapper(cppobj); if (pyobj) Py_INCREF(pyobj); else pyobj = createWrapper(cppobj); return pyobj; } static T* toCpp(PyObject* pyobj) { if (pyobj == Py_None) return 0; else if (Shiboken_TypeCheck(pyobj, T)) return (T*) SbkBaseWrapper_cptr(pyobj); else if (Converter::isConvertible(pyobj)) return CppObjectCopier::copy(Converter::toCpp(pyobj)); return 0; } }; template struct Converter : Converter {}; // Specialization for reference conversions. template struct Converter { 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); } }; template struct Converter : Converter {}; // Void pointer conversions. template<> struct Converter { static inline bool isConvertible(PyObject* pyobj) { return true; } static PyObject* toPython(const void* cppobj) { if (!cppobj) Py_RETURN_NONE; PyObject* pyobj = BindingManager::instance().retrieveWrapper(cppobj); if (pyobj) Py_INCREF(pyobj); else pyobj = SbkBaseWrapper_New(&SbkBaseWrapper_Type, cppobj, false, false); return pyobj; } static void* toCpp(PyObject* pyobj) { if (pyobj == Py_None) return 0; return SbkBaseWrapper_cptr(pyobj); } }; template <> struct Converter : Converter {}; // Base converter meant to be inherited by converters for classes that could be // passed by value. // Example: "struct Converter : ValueTypeConverter" template struct ValueTypeConverter { // 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; SbkBaseWrapperType* shiboType = reinterpret_cast(SbkType()); if (shiboType->ext_isconvertible) return shiboType->ext_isconvertible(pyobj); return false; } static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } static inline PyObject* toPython(const T& cppobj) { PyObject* obj = createWrapper(CppObjectCopier::copy(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) { PyTypeObject* typeObj = SbkType(); if (typeObj->ob_type == &Shiboken::SbkBaseWrapperType_Type) { SbkBaseWrapperType* shiboType = reinterpret_cast(typeObj); if (shiboType->ext_tocpp && isConvertible(pyobj)) { T* cptr = reinterpret_cast(shiboType->ext_tocpp(pyobj)); std::auto_ptr cptr_auto_ptr(cptr); return *cptr; } } return *reinterpret_cast(reinterpret_cast(pyobj)->cptr); } }; // 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 { /// 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 = 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; SbkBaseWrapperType* shiboType = reinterpret_cast(pyobj->ob_type); if (shiboType->mi_specialcast) return (T*) shiboType->mi_specialcast(SbkBaseWrapper_cptr(pyobj), reinterpret_cast(SbkType())); return (T*) SbkBaseWrapper_cptr(pyobj); } }; template struct ObjectTypeReferenceConverter : ObjectTypeConverter { 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; } }; template <> struct Converter : Converter {}; // Primitive Conversions ------------------------------------------------------ template <> struct Converter { 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 pyobj == Py_True; } }; /** * 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& value) { return false; } }; template<> struct OverFlowChecker { static bool check(const double& value) { 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 isConvertible(PyObject* pyobj) { return PyNumber_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); } }; /// Check if we can treat the pyobj as a char, i.e. it's a number or a string with just one character. #define SbkChar_Check(pyobj) (PyNumber_Check(pyobj) || (PyString_Check(pyobj) && PyString_Size(pyobj) == 1)) /// Specialization to convert char and unsigned char, it accepts Python numbers and strings with just one character. template struct CharConverter { 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 (PyString_Check(pyobj)) { assert(PyString_Size(pyobj) == 1); // This check is made on SbkChar_Check return PyString_AS_STRING(pyobj)[0]; } else { PY_LONG_LONG result = PyLong_AsLongLong(pyobj); if (OverFlowChecker::check(result)) PyErr_SetObject(PyExc_OverflowError, 0); return result; } } }; template <> struct Converter : Converter_PyULongInt {}; template <> struct Converter : Converter_PyULongInt {}; template <> struct Converter : CharConverter { // Should we really return a string? using CharConverter::toPython; static inline PyObject* toPython(const char& cppObj) { return PyString_FromFormat("%c", cppObj); } }; 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) { return (unsigned PY_LONG_LONG) PyLong_AsUnsignedLongLong(pyobj); } }; template struct Converter_PyFloat { static inline bool isConvertible(PyObject* obj) { return PyNumber_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 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 SbkEnumObject_New(SbkType(), (long) cppenum); } static inline CppEnum toCpp(PyObject* pyobj) { return (CppEnum) reinterpret_cast(pyobj)->ob_ival; } }; // C Sting Types -------------------------------------------------------------- template struct Converter_CString { static inline bool isConvertible(PyObject* pyObj) { return pyObj == Py_None || PyString_Check(pyObj); } static inline PyObject* toPython(void* cppobj) { return toPython(reinterpret_cast(cppobj)); } static inline PyObject* toPython(CString cppobj) { if (!cppobj) Py_RETURN_NONE; return PyString_FromString(cppobj); } static inline CString toCpp(PyObject* pyobj) { if (pyobj == Py_None) return 0; return PyString_AsString(pyobj); } }; template <> struct Converter : Converter_CString {}; template <> struct Converter : Converter_CString {}; // 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 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() && isShibokenType(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(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(SbkBaseWrapper_cptr(pyobj)); StdList result; for (int i = 0; i < PySequence_Size(pyobj); i++) { PyObject* pyItem = PySequence_GetItem(pyobj, i); result.push_back(Converter::toCpp(pyItem)); } return result; } }; template struct StdPairConverter { static inline bool isConvertible(PyObject* pyObj) { if (PyObject_TypeCheck(pyObj, SbkType())) return true; if ((SbkType() && isShibokenType(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(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 isConvertible(PyObject* pyObj) { if (PyObject_TypeCheck(pyObj, SbkType())) return true; if ((SbkType() && isShibokenType(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(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; } }; } // namespace Shiboken #endif // CONVERSIONS_H