summaryrefslogtreecommitdiffstats
path: root/libshiboken
diff options
context:
space:
mode:
authorMarcelo Lira <marcelo.lira@openbossa.org>2011-08-16 16:03:21 -0300
committerMarcelo Lira <marcelo.lira@openbossa.org>2011-12-09 20:28:06 -0300
commit11eda546a3bc3133ab180c6be5723f10a2abcf22 (patch)
treed5e489f838a9e39e23ebd86c76a023c5c5c03d2f /libshiboken
parent3783e1c72b5497c5564a02308efb0b1fc7d4e224 (diff)
downloadshiboken-11eda546a3bc3133ab180c6be5723f10a2abcf22.tar.gz
shiboken-11eda546a3bc3133ab180c6be5723f10a2abcf22.tar.xz
shiboken-11eda546a3bc3133ab180c6be5723f10a2abcf22.zip
New converters for C++ primitive types.
Diffstat (limited to 'libshiboken')
-rw-r--r--libshiboken/basewrapper.cpp2
-rw-r--r--libshiboken/sbkconverter.cpp32
-rw-r--r--libshiboken/sbkconverter.h44
-rw-r--r--libshiboken/sbkconverter_p.h367
4 files changed, 443 insertions, 2 deletions
diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp
index 181b7025..fc83d44c 100644
--- a/libshiboken/basewrapper.cpp
+++ b/libshiboken/basewrapper.cpp
@@ -462,6 +462,7 @@ void DeallocVisitor::done()
}
namespace Module { void init(); }
+namespace Conversions { void init(); }
void init()
{
@@ -470,6 +471,7 @@ void init()
return;
Module::init();
+ Conversions::init();
initTypeResolver();
PyEval_InitThreads();
diff --git a/libshiboken/sbkconverter.cpp b/libshiboken/sbkconverter.cpp
index c5e64f3d..34705d9e 100644
--- a/libshiboken/sbkconverter.cpp
+++ b/libshiboken/sbkconverter.cpp
@@ -26,9 +26,35 @@
#include "sbkdbg.h"
+static SbkConverter** PrimitiveTypeConverters;
+
namespace Shiboken {
namespace Conversions {
+void init()
+{
+ static SbkConverter* primitiveTypeConverters[] = {
+ Primitive<PY_LONG_LONG>::createConverter(),
+ Primitive<bool>::createConverter(),
+ Primitive<char>::createConverter(),
+ Primitive<const char*>::createConverter(),
+ Primitive<double>::createConverter(),
+ Primitive<float>::createConverter(),
+ Primitive<int>::createConverter(),
+ Primitive<long>::createConverter(),
+ Primitive<short>::createConverter(),
+ Primitive<signed char>::createConverter(),
+ Primitive<std::string>::createConverter(),
+ Primitive<unsigned PY_LONG_LONG>::createConverter(),
+ Primitive<unsigned char>::createConverter(),
+ Primitive<unsigned int>::createConverter(),
+ Primitive<unsigned long>::createConverter(),
+ Primitive<unsigned short>::createConverter(),
+ Primitive<void*>::createConverter()
+ };
+ PrimitiveTypeConverters = primitiveTypeConverters;
+}
+
static SbkConverter* createConverterObject(PyTypeObject* type,
PythonToCppFunc toCppPointerConvFunc,
IsConvertibleToCppFunc toCppPointerCheckFunc,
@@ -113,7 +139,6 @@ PyObject* referenceToPython(SbkObjectType* type, const void* cppIn)
static inline PyObject* CopyCppToPython(SbkConverter* converter, const void* cppIn)
{
- assert(cppIn);
return converter->copyToPython(cppIn);
}
PyObject* copyToPython(SbkObjectType* type, const void* cppIn)
@@ -228,4 +253,9 @@ bool isImplicitConversion(SbkObjectType* type, PythonToCppFunc toCppFunc)
return toCppFunc != (*conv).second;
}
+SbkConverter* primitiveTypeConverter(int index)
+{
+ return PrimitiveTypeConverters[index];
+}
+
} } // namespace Shiboken::Conversions
diff --git a/libshiboken/sbkconverter.h b/libshiboken/sbkconverter.h
index 1d539248..6c10df2a 100644
--- a/libshiboken/sbkconverter.h
+++ b/libshiboken/sbkconverter.h
@@ -36,6 +36,8 @@
#define SbkObject_TypeCheck(tp, ob) \
(Py_TYPE(ob) == (tp) || PyType_IsSubtype(Py_TYPE(ob), (tp)))
+#define SbkString_Check(pyObj) (pyObj == Py_None || PyString_Check(pyObj))
+
extern "C"
{
@@ -83,7 +85,6 @@ typedef PythonToCppFunc (*IsConvertibleToCppFunc)(PyObject*);
} // extern "C"
-
namespace Shiboken {
namespace Conversions {
@@ -211,6 +212,47 @@ LIBSHIBOKEN_API void nonePythonToCppNullPtr(PyObject*, void* cppOut);
*/
LIBSHIBOKEN_API bool isImplicitConversion(SbkObjectType* type, PythonToCppFunc toCpp);
+/// Returns the converter for a primitive type.
+LIBSHIBOKEN_API SbkConverter* primitiveTypeConverter(int index);
+
+#define SBK_PY_LONG_LONG_IDX 0
+#define SBK_BOOL_IDX 1
+#define SBK_CHAR_IDX 2
+#define SBK_CONSTCHARPTR_IDX 3
+#define SBK_DOUBLE_IDX 4
+#define SBK_FLOAT_IDX 5
+#define SBK_INT_IDX 6
+#define SBK_SIGNEDINT_IDX 6
+#define SBK_LONG_IDX 7
+#define SBK_SHORT_IDX 8
+#define SBK_SIGNEDCHAR_IDX 9
+#define SBK_STD_STRING_IDX 10
+#define SBK_UNSIGNEDPY_LONG_LONG_IDX 11
+#define SBK_UNSIGNEDCHAR_IDX 12
+#define SBK_UNSIGNEDINT_IDX 13
+#define SBK_UNSIGNEDLONG_IDX 14
+#define SBK_UNSIGNEDSHORT_IDX 15
+#define SBK_VOIDPTR_IDX 16
+
+template<typename T> SbkConverter* PrimitiveTypeConverter() { return 0; }
+template<> inline SbkConverter* PrimitiveTypeConverter<PY_LONG_LONG>() { return primitiveTypeConverter(SBK_PY_LONG_LONG_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<bool>() { return primitiveTypeConverter(SBK_BOOL_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<char>() { return primitiveTypeConverter(SBK_CHAR_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<const char*>() { return primitiveTypeConverter(SBK_CONSTCHARPTR_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<double>() { return primitiveTypeConverter(SBK_DOUBLE_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<float>() { return primitiveTypeConverter(SBK_FLOAT_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<int>() { return primitiveTypeConverter(SBK_INT_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<long>() { return primitiveTypeConverter(SBK_LONG_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<short>() { return primitiveTypeConverter(SBK_SHORT_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<signed char>() { return primitiveTypeConverter(SBK_SIGNEDCHAR_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<std::string>() { return primitiveTypeConverter(SBK_STD_STRING_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<unsigned PY_LONG_LONG>() { return primitiveTypeConverter(SBK_UNSIGNEDPY_LONG_LONG_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<unsigned char>() { return primitiveTypeConverter(SBK_UNSIGNEDCHAR_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<unsigned int>() { return primitiveTypeConverter(SBK_UNSIGNEDINT_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<unsigned long>() { return primitiveTypeConverter(SBK_UNSIGNEDLONG_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<unsigned short>() { return primitiveTypeConverter(SBK_UNSIGNEDSHORT_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<void*>() { return primitiveTypeConverter(SBK_VOIDPTR_IDX); }
+
} } // namespace Shiboken::Conversions
#endif // SBK_CONVERTER_H
diff --git a/libshiboken/sbkconverter_p.h b/libshiboken/sbkconverter_p.h
index 199538cc..8abdc297 100644
--- a/libshiboken/sbkconverter_p.h
+++ b/libshiboken/sbkconverter_p.h
@@ -25,8 +25,11 @@
#include <Python.h>
#include <list>
+#include <limits>
#include "sbkconverter.h"
+#include "sbkdbg.h"
+
extern "C"
{
@@ -87,4 +90,368 @@ struct SbkConverter
} // extern "C"
+// Helper template for checking if a value overflows when cast 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& value) { return false; }
+};
+template<>
+struct OverFlowChecker<double, true> {
+ static bool check(const double& value) { 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();
+ }
+};
+
+// 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 {};
+
+template <typename T>
+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<T>(), Primitive<T>::toPython);
+ Shiboken::Conversions::addPythonToCppValueConversion(converter, Primitive<T>::toCpp, Primitive<T>::isConvertible);
+ return converter;
+ }
+};
+template <typename T>
+struct TwoPrimitive : OnePrimitive<T>
+{
+ static PythonToCppFunc isOtherConvertible(PyObject*) { return 0; }
+ static void otherToCpp(PyObject*, void*) {}
+ static SbkConverter* createConverter()
+ {
+ SbkConverter* converter = OnePrimitive<T>::createConverter();
+ Shiboken::Conversions::addPythonToCppValueConversion(converter, Primitive<T>::otherToCpp, Primitive<T>::isOtherConvertible);
+ return converter;
+ }
+};
+
+// Integers --------------------------------------------------------------------------------
+
+// Note: if there wasn't for the old-style classes, a simple PyNumber_Check would suffice.
+#define SbkNumber_Check(X) (PyNumber_Check(X) \
+ && (!PyInstance_Check(X) || PyObject_HasAttrString(X, "__trunc__")))
+
+template <typename INT>
+struct IntPrimitive : TwoPrimitive<INT>
+{
+ 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<INT>::check(result))
+ PyErr_SetObject(PyExc_OverflowError, 0);
+ *((INT*)cppOut) = static_cast<INT>(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<INT>::check(result))
+ PyErr_SetObject(PyExc_OverflowError, 0);
+ *((INT*)cppOut) = static_cast<INT>(result);
+ }
+ static PythonToCppFunc isOtherConvertible(PyObject* pyIn)
+ {
+ if (SbkNumber_Check(pyIn))
+ return otherToCpp;
+ return 0;
+ }
+};
+template <> struct Primitive<int> : IntPrimitive<int> {};
+template <> struct Primitive<long> : IntPrimitive<long> {};
+template <> struct Primitive<short> : IntPrimitive<short> {};
+template <> struct Primitive<unsigned short> : IntPrimitive<unsigned short> {};
+
+// Unsigned Long Integers ------------------------------------------------------------------
+
+template <typename LONG>
+struct UnsignedLongPrimitive : IntPrimitive<LONG>
+{
+ static PyObject* toPython(const void* cppIn)
+ {
+ return PyLong_FromUnsignedLong(*((LONG*)cppIn));
+ }
+};
+template <> struct Primitive<unsigned int> : UnsignedLongPrimitive<unsigned int> {};
+template <> struct Primitive<unsigned long> : UnsignedLongPrimitive<unsigned long> {};
+
+// Big integers ----------------------------------------------------------------------------
+
+template <>
+struct Primitive<PY_LONG_LONG> : OnePrimitive<PY_LONG_LONG>
+{
+ 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<unsigned PY_LONG_LONG> : OnePrimitive<unsigned PY_LONG_LONG>
+{
+ static PyObject* toPython(const void* cppIn)
+ {
+ return PyLong_FromUnsignedLongLong(*((unsigned PY_LONG_LONG*)cppIn));
+ }
+ static void toCpp(PyObject* pyIn, void* cppOut)
+ {
+ *((unsigned PY_LONG_LONG*)cppOut) = (unsigned PY_LONG_LONG) PyLong_AsUnsignedLongLong(pyIn);
+ }
+ static PythonToCppFunc isConvertible(PyObject* pyIn)
+ {
+ if (SbkNumber_Check(pyIn))
+ return toCpp;
+ return 0;
+ }
+};
+
+// Floating point --------------------------------------------------------------------------
+
+template <typename FLOAT>
+struct FloatPrimitive : TwoPrimitive<FLOAT>
+{
+ 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<float> : FloatPrimitive<float> {};
+template <> struct Primitive<double> : FloatPrimitive<double> {};
+
+// Boolean ---------------------------------------------------------------------------------
+
+template <>
+struct Primitive<bool> : OnePrimitive<bool>
+{
+ 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 <typename CHAR>
+struct CharPrimitive : IntPrimitive<CHAR>
+{
+ static void toCpp(PyObject* pyIn, void* cppOut)
+ {
+ *((CHAR*)cppOut) = (CHAR) PyString_AS_STRING(pyIn)[0];
+ }
+ static PythonToCppFunc isConvertible(PyObject* pyIn)
+ {
+ if (PyString_Check(pyIn) && PyString_Size(pyIn) == 1)
+ return toCpp;
+ return 0;
+ }
+ static void otherToCpp(PyObject* pyIn, void* cppOut)
+ {
+ PY_LONG_LONG result = PyLong_AsLongLong(pyIn);
+ if (OverFlowChecker<CHAR>::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<CHAR>::createConverter();
+ Shiboken::Conversions::addPythonToCppValueConversion(converter, CharPrimitive<CHAR>::otherToCpp, CharPrimitive<CHAR>::isOtherConvertible);
+ return converter;
+ }
+
+};
+template <> struct Primitive<signed char> : CharPrimitive<signed char> {};
+template <> struct Primitive<unsigned char> : CharPrimitive<unsigned char> {};
+template <> struct Primitive<char> : CharPrimitive<char> {
+ using CharPrimitive<char>::toPython;
+ static PyObject* toPython(const void* cppIn) {
+ return PyString_FromFormat("%c", *((const char*)cppIn));
+ }
+};
+
+
+
+// Strings ---------------------------------------------------------------------------------
+
+template <>
+struct Primitive<const char*> : TwoPrimitive<const char*>
+{
+ static PyObject* toPython(const void* cppIn)
+ {
+ if (!cppIn)
+ Py_RETURN_NONE;
+ return PyString_FromString((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*) PyString_AsString(pyIn);
+ }
+ static PythonToCppFunc isOtherConvertible(PyObject* pyIn)
+ {
+ if (PyString_Check(pyIn))
+ return otherToCpp;
+ return 0;
+ }
+};
+
+template <>
+struct Primitive<std::string> : TwoPrimitive<std::string>
+{
+ static PyObject* toPython(const void* cppIn)
+ {
+ return PyString_FromString(((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) = std::string(PyString_AsString(pyIn));
+ }
+ static PythonToCppFunc isOtherConvertible(PyObject* pyIn)
+ {
+ if (PyString_Check(pyIn))
+ return otherToCpp;
+ return 0;
+ }
+};
+
+// Void pointer ----------------------------------------------------------------------------
+
+template <>
+struct Primitive<void*> : OnePrimitive<void*>
+{
+ 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