diff options
-rw-r--r-- | headergenerator.cpp | 8 | ||||
-rw-r--r-- | libshiboken/conversions.h | 127 | ||||
-rw-r--r-- | tests/samplebinding/complex_conversions.h | 4 | ||||
-rw-r--r-- | tests/samplebinding/oddbool_conversions.h | 4 |
4 files changed, 77 insertions, 66 deletions
diff --git a/headergenerator.cpp b/headergenerator.cpp index 0e16a9968..ee5c03753 100644 --- a/headergenerator.cpp +++ b/headergenerator.cpp @@ -167,10 +167,12 @@ void HeaderGenerator::writeTypeConverterDecl(QTextStream& s, const TypeEntry* ty s << "struct Converter<" << type->name() << (isAbstractOrObjectType ? "*" : "") << " > : "; if (type->isEnum() || type->isFlags()) - s << "Converter_CppEnum"; + s << "EnumConverter"; + else if (isAbstractOrObjectType) + s << "ObjectTypeConverter"; else - s << "ConverterBase"; - s << '<' << type->name() << (isAbstractOrObjectType ? "*" : "") << " >" << endl; + s << "ValueTypeConverter"; + s << '<' << type->name() << " >" << endl; s << '{' << endl; if (isValueTypeWithImplConversions) { s << INDENT << "static " << type->name() << " toCpp(PyObject* pyobj);" << endl; diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index 5b559308e..3c14df321 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -118,59 +118,16 @@ inline PyObject* createWrapper(const T* cppobj, bool hasOwnership = false, bool } // Base Conversions ---------------------------------------------------------- -template <typename T> struct Converter; - -template <typename T> -struct ConverterBase -{ - static inline bool isConvertible(PyObject* pyobj) { return pyobj == Py_None; } - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<T*>(cppobj)); } - static inline PyObject* toPython(const T& cppobj) - { - PyObject* obj = createWrapper<T>(CppObjectCopier<T>::copy(cppobj), true, true); - SbkBaseWrapper_setContainsCppWrapper(obj, SbkTypeInfo<T>::isCppWrapper); - return obj; - } - // Classes with implicit conversions are expected to reimplement - // this to build T from its various implicit constructors. - static inline T toCpp(PyObject* pyobj) { return *Converter<T*>::toCpp(pyobj); } -}; - -// Specialization meant to be used by abstract classes and object-types -// (i.e. classes with private copy constructors and = operators). -// Example: "struct Converter<AbstractClass* > : ConverterBase<AbstractClass* >" -template <typename T> -struct ConverterBase<T*> : ConverterBase<T> -{ - static inline PyObject* toPython(void* cppobj) { return toPython(reinterpret_cast<T*>(cppobj)); } - 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<T>(cppobj); - return pyobj; - } - static T* toCpp(PyObject* pyobj) - { - if (pyobj == Py_None) - return 0; - SbkBaseWrapperType* shiboType = reinterpret_cast<SbkBaseWrapperType*>(pyobj->ob_type); - if (shiboType->mi_specialcast) - return (T*) shiboType->mi_specialcast(pyobj, reinterpret_cast<SbkBaseWrapperType*>(SbkType<T>())); - return (T*) SbkBaseWrapper_cptr(pyobj); - } -}; - -// Pointer 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*> : Converter<T> { + /// Value type pointers should be convertible only to NULL pointers, represented in Python by a 'None' object. + static inline bool isConvertible(PyObject* pyobj) { return pyobj == Py_None; } + /// Convenience overload that calls "toPython(const T*)" method. static inline PyObject* toPython(void* cppobj) { return toPython(reinterpret_cast<T*>(cppobj)); } static PyObject* toPython(const T* cppobj) { @@ -194,15 +151,7 @@ struct Converter<T*> : Converter<T> }; template <typename T> struct Converter<const T*> : Converter<T*> {}; -// PyObject* specialization to avoid converting what doesn't need to be converted. -template<> -struct Converter<PyObject*> : ConverterBase<PyObject*> -{ - static inline PyObject* toCpp(PyObject* pyobj) { return pyobj; } -}; -template <> struct Converter<const PyObject*> : Converter<PyObject*> {}; - -// Reference Conversions +// Specialization for reference conversions. template <typename T> struct Converter<T&> : Converter<T*> { @@ -212,7 +161,7 @@ struct Converter<T&> : Converter<T*> }; template <typename T> struct Converter<const T&> : Converter<T&> {}; -// Void pointer conversions +// Void pointer conversions. template<> struct Converter<void*> { @@ -235,6 +184,66 @@ struct Converter<void*> }; template <> struct Converter<const void*> : Converter<void*> {}; +// 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 isConvertible(PyObject* pyobj) { return false; } + static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<T*>(cppobj)); } + static inline PyObject* toPython(const T& cppobj) + { + PyObject* obj = createWrapper<T>(CppObjectCopier<T>::copy(cppobj), true, true); + SbkBaseWrapper_setContainsCppWrapper(obj, SbkTypeInfo<T>::isCppWrapper); + return obj; + } + // Classes with implicit conversions are expected to reimplement + // this to build T from its various implicit constructors. + static inline T toCpp(PyObject* pyobj) { return *Converter<T*>::toCpp(pyobj); } +}; + +// 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 +{ + /// 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; } + /// 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 = 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; + SbkBaseWrapperType* shiboType = reinterpret_cast<SbkBaseWrapperType*>(pyobj->ob_type); + if (shiboType->mi_specialcast) + return (T*) shiboType->mi_specialcast(pyobj, reinterpret_cast<SbkBaseWrapperType*>(SbkType<T>())); + return (T*) SbkBaseWrapper_cptr(pyobj); + } +}; + +// 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; } +}; +template <> struct Converter<const PyObject*> : Converter<PyObject*> {}; // Primitive Conversions ------------------------------------------------------ template <> @@ -411,7 +420,7 @@ template <> struct Converter<double> : Converter_PyFloat<double> {}; // PyEnum Conversions --------------------------------------------------------- template <typename CppEnum> -struct Converter_CppEnum +struct EnumConverter { static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<CppEnum*>(cppobj)); } static inline PyObject* toPython(CppEnum cppenum) diff --git a/tests/samplebinding/complex_conversions.h b/tests/samplebinding/complex_conversions.h index ef3fd31ae..6a69b26f3 100644 --- a/tests/samplebinding/complex_conversions.h +++ b/tests/samplebinding/complex_conversions.h @@ -1,13 +1,13 @@ namespace Shiboken { template<> -struct Converter<Complex> : public ConverterBase<Complex> +struct Converter<Complex> : public ValueTypeConverter<Complex> { static bool isConvertible(const PyObject* pyObj) { return PyComplex_Check(pyObj); } - using ConverterBase<Complex>::toPython; + using ValueTypeConverter<Complex>::toPython; static PyObject* toPython(const Complex& cpx) { diff --git a/tests/samplebinding/oddbool_conversions.h b/tests/samplebinding/oddbool_conversions.h index 923835968..452b94725 100644 --- a/tests/samplebinding/oddbool_conversions.h +++ b/tests/samplebinding/oddbool_conversions.h @@ -1,13 +1,13 @@ namespace Shiboken { template <> -struct Converter<OddBool> : public ConverterBase<OddBool> +struct Converter<OddBool> : public ValueTypeConverter<OddBool> { static bool isConvertible(const PyObject* pyObj) { return PyBool_Check(pyObj); } - using ConverterBase<OddBool>::toPython; + using ValueTypeConverter<OddBool>::toPython; static PyObject* toPython(const OddBool& holder) { |