/* * This file is part of the Shiboken Python Bindings Generator project. * * Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). * * Contact: PySide team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef SBK_CONVERTER_P_H #define SBK_CONVERTER_P_H #include "sbkpython.h" #include "sbkconverter.h" #include "sbkstring.h" #include #include #include "sbkdbg.h" extern "C" { typedef std::pair ToCppConversion; typedef std::list ToCppConversionList; /** * \internal * Private structure of SbkConverter. */ struct SbkConverter { /** * Python type associated with this converter. If the type is a Shiboken * wrapper, then it must be a SbkObjectType; otherwise it will be the * Python type to which the C++ value will be converted (note that the * C++ type could be produced from various Python types). */ PyTypeObject* pythonType; /** * This function converts a C++ object to a Python object of the type * indicated in pythonType. The identity of the C++ object is kept, * because it looks for an already existing Python wrapper associated * with the C++ instance. * It is used to convert C++ pointers and references to Python objects. */ CppToPythonFunc pointerToPython; /** * This function converts a C++ object to a Python object of the type * indicated in pythonType. The identity of the object is not kept, * because a new instance of the C++ object is created. * It is used to convert objects passed by value, or reference, if said * reference can't be traced to an object that already has a Python * wrapper assigned for it. */ CppToPythonFunc copyToPython; /** * This is a special case of a Python to C++ conversion. It returns * the underlying C++ pointer of a Python wrapper passed as parameter * or NULL if the Python object is a None value. * It comes separated from the other toCppConversions because if you * have a Python object representing a Value Type the type checking * for both ValueType and ValueType* would be the same, thus the first * check would be true and the second would never be reached. */ ToCppConversion toCppPointerConversion; /** * This is a list of type checking functions that return the * proper Python to C++ conversion function, for the given Python * object. * For Object Types, that never have implicit conversions, this * list is always empty. */ ToCppConversionList toCppConversions; }; } // extern "C" // Helper template for checking if a value overflows when cast 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(); } }; // 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 {}; template struct OnePrimitive { static PyObject* toPython(const void*) { return 0; } static PythonToCppFunc isConvertible(PyObject*) { return 0; } static void toCpp(PyObject*, void*) {} static SbkConverter* createConverter() { SbkConverter* converter = Shiboken::Conversions::createConverter(SbkType(), Primitive::toPython); Shiboken::Conversions::addPythonToCppValueConversion(converter, Primitive::toCpp, Primitive::isConvertible); return converter; } }; template struct TwoPrimitive : OnePrimitive { static PythonToCppFunc isOtherConvertible(PyObject*) { return 0; } static void otherToCpp(PyObject*, void*) {} static SbkConverter* createConverter() { SbkConverter* converter = OnePrimitive::createConverter(); Shiboken::Conversions::addPythonToCppValueConversion(converter, Primitive::otherToCpp, Primitive::isOtherConvertible); return converter; } }; // Integers -------------------------------------------------------------------------------- template struct IntPrimitive : TwoPrimitive { static PyObject* toPython(const void* cppIn) { return PyInt_FromLong((long)*((INT*)cppIn)); } static void toCpp(PyObject* pyIn, void* cppOut) { double result = PyFloat_AS_DOUBLE(pyIn); // If cast to long directly it could overflow silently. if (OverFlowChecker::check(result)) PyErr_SetObject(PyExc_OverflowError, 0); *((INT*)cppOut) = static_cast(result); } static PythonToCppFunc isConvertible(PyObject* pyIn) { if (PyFloat_Check(pyIn)) return toCpp; return 0; } static void otherToCpp(PyObject* pyIn, void* cppOut) { PY_LONG_LONG result = PyLong_AsLongLong(pyIn); if (OverFlowChecker::check(result)) PyErr_SetObject(PyExc_OverflowError, 0); *((INT*)cppOut) = static_cast(result); } static PythonToCppFunc isOtherConvertible(PyObject* pyIn) { if (SbkNumber_Check(pyIn)) return otherToCpp; return 0; } }; template <> struct Primitive : IntPrimitive {}; template <> struct Primitive : IntPrimitive {}; template <> struct Primitive : IntPrimitive {}; template <> struct Primitive : IntPrimitive {}; // Unsigned Long Integers ------------------------------------------------------------------ template struct UnsignedLongPrimitive : IntPrimitive { static PyObject* toPython(const void* cppIn) { return PyLong_FromUnsignedLong(*((LONG*)cppIn)); } }; template <> struct Primitive : UnsignedLongPrimitive {}; template <> struct Primitive : UnsignedLongPrimitive {}; // Big integers ---------------------------------------------------------------------------- template <> struct Primitive : OnePrimitive { static PyObject* toPython(const void* cppIn) { return PyLong_FromLongLong(*((PY_LONG_LONG*)cppIn)); } static void toCpp(PyObject* pyIn, void* cppOut) { *((PY_LONG_LONG*)cppOut) = (PY_LONG_LONG) PyLong_AsLongLong(pyIn); } static PythonToCppFunc isConvertible(PyObject* pyIn) { if (SbkNumber_Check(pyIn)) return toCpp; return 0; } }; template <> struct Primitive : OnePrimitive { static PyObject* toPython(const void* cppIn) { return PyLong_FromUnsignedLongLong(*((unsigned PY_LONG_LONG*)cppIn)); } static void toCpp(PyObject* pyIn, void* cppOut) { if (PyInt_Check(pyIn)) { long result = (unsigned PY_LONG_LONG) PyInt_AsLong(pyIn); if (result < 0) PyErr_SetObject(PyExc_OverflowError, 0); else *((unsigned PY_LONG_LONG*)cppOut) = (unsigned PY_LONG_LONG) result; } else if (PyLong_Check(pyIn)) { *((unsigned PY_LONG_LONG*)cppOut) = (unsigned PY_LONG_LONG) PyLong_AsUnsignedLongLong(pyIn); } else { PyErr_SetString(PyExc_TypeError, "Invalid type for unsigned long long conversion"); } } static PythonToCppFunc isConvertible(PyObject* pyIn) { if (SbkNumber_Check(pyIn)) return toCpp; return 0; } }; // Floating point -------------------------------------------------------------------------- template struct FloatPrimitive : TwoPrimitive { static PyObject* toPython(const void* cppIn) { return PyFloat_FromDouble((double)*((FLOAT*)cppIn)); } static void toCpp(PyObject* pyIn, void* cppOut) { *((FLOAT*)cppOut) = (FLOAT) PyLong_AsLong(pyIn); } static PythonToCppFunc isConvertible(PyObject* pyIn) { if (PyInt_Check(pyIn) || PyLong_Check(pyIn)) return toCpp; return 0; } static void otherToCpp(PyObject* pyIn, void* cppOut) { *((FLOAT*)cppOut) = (FLOAT) PyFloat_AsDouble(pyIn); } static PythonToCppFunc isOtherConvertible(PyObject* pyIn) { if (SbkNumber_Check(pyIn)) return otherToCpp; return 0; } }; template <> struct Primitive : FloatPrimitive {}; template <> struct Primitive : FloatPrimitive {}; // Boolean --------------------------------------------------------------------------------- template <> struct Primitive : OnePrimitive { static PyObject* toPython(const void* cppIn) { return PyBool_FromLong(*((bool*)cppIn)); } static PythonToCppFunc isConvertible(PyObject* pyIn) { if (SbkNumber_Check(pyIn)) return toCpp; return 0; } static void toCpp(PyObject* pyIn, void* cppOut) { *((bool*)cppOut) = (bool) PyInt_AS_LONG(pyIn); } }; // Characters ------------------------------------------------------------------------------ template struct CharPrimitive : IntPrimitive { static void toCpp(PyObject* pyIn, void* cppOut) { *((CHAR*)cppOut) = (CHAR) Shiboken::String::toCString(pyIn)[0]; } static PythonToCppFunc isConvertible(PyObject* pyIn) { if (Shiboken::String::checkChar(pyIn)) return toCpp; return 0; } static void otherToCpp(PyObject* pyIn, void* cppOut) { PY_LONG_LONG result = PyLong_AsLongLong(pyIn); if (OverFlowChecker::check(result)) PyErr_SetObject(PyExc_OverflowError, 0); *((CHAR*)cppOut) = (CHAR) result; } static PythonToCppFunc isOtherConvertible(PyObject* pyIn) { if (SbkNumber_Check(pyIn)) return otherToCpp; return 0; } static SbkConverter* createConverter() { SbkConverter* converter = IntPrimitive::createConverter(); Shiboken::Conversions::addPythonToCppValueConversion(converter, CharPrimitive::otherToCpp, CharPrimitive::isOtherConvertible); return converter; } }; template <> struct Primitive : CharPrimitive {}; template <> struct Primitive : CharPrimitive {}; template <> struct Primitive : CharPrimitive { using CharPrimitive::toPython; static PyObject* toPython(const void* cppIn) { return Shiboken::String::fromCString((const char*)cppIn, 1); } }; // Strings --------------------------------------------------------------------------------- template <> struct Primitive : TwoPrimitive { static PyObject* toPython(const void* cppIn) { if (!cppIn) Py_RETURN_NONE; return Shiboken::String::fromCString((const char*)cppIn); } static void toCpp(PyObject* pyIn, void* cppOut) { *((const char**)cppOut) = 0; } static PythonToCppFunc isConvertible(PyObject* pyIn) { if (pyIn == Py_None) return toCpp; return 0; } static void otherToCpp(PyObject* pyIn, void* cppOut) { *((const char**)cppOut) = (const char*) Shiboken::String::toCString(pyIn); } static PythonToCppFunc isOtherConvertible(PyObject* pyIn) { if (Shiboken::String::check(pyIn)) return otherToCpp; return 0; } }; template <> struct Primitive : TwoPrimitive { static PyObject* toPython(const void* cppIn) { return Shiboken::String::fromCString(((std::string*)cppIn)->c_str()); } static void toCpp(PyObject* pyIn, void* cppOut) { *((std::string*)cppOut) = std::string(); } static PythonToCppFunc isConvertible(PyObject* pyIn) { if (pyIn == Py_None) return toCpp; return 0; } static void otherToCpp(PyObject* pyIn, void* cppOut) { *((std::string*)cppOut) = Shiboken::String::toCString(pyIn); } static PythonToCppFunc isOtherConvertible(PyObject* pyIn) { if (Shiboken::String::check(pyIn)) return otherToCpp; return 0; } }; // Void pointer ---------------------------------------------------------------------------- template <> struct Primitive : OnePrimitive { static PyObject* toPython(const void* cppIn) { SbkDbg() << cppIn; if (!cppIn) Py_RETURN_NONE; PyObject* result = (PyObject*) cppIn; Py_INCREF(result); return result; } static void toCpp(PyObject* pyIn, void* cppOut) { SbkDbg() << pyIn; *((void**)cppOut) = pyIn; } static PythonToCppFunc isConvertible(PyObject* pyIn) { return toCpp; } }; #endif // SBK_CONVERTER_P_H