From d25db2975162f592892313e10938531d8505e6c4 Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Fri, 4 Nov 2011 20:01:33 -0300 Subject: Added adapter class SpecificConverter to provide type conversion based on a given string. Also added code to register a couple of type conversions by name, a bunch of related tests, and some fixes to the converter functions. --- libshiboken/sbkconverter.cpp | 63 +++++++++++++++++++++++++++++++++++++------- libshiboken/sbkconverter.h | 33 +++++++++++++++++++++-- 2 files changed, 84 insertions(+), 12 deletions(-) (limited to 'libshiboken') diff --git a/libshiboken/sbkconverter.cpp b/libshiboken/sbkconverter.cpp index ef332831..edd7097d 100644 --- a/libshiboken/sbkconverter.cpp +++ b/libshiboken/sbkconverter.cpp @@ -172,17 +172,12 @@ PyObject* referenceToPython(SbkConverter* converter, const void* cppIn) { assert(cppIn); - // If it is a Object Type, produce a wrapper for it. - if (!converter->copyToPython) - return converter->pointerToPython(cppIn); - - // If it is a Value Type, try to find an existing wrapper, otherwise copy it as value to Python. PyObject* pyOut = (PyObject*)BindingManager::instance().retrieveWrapper(cppIn); if (pyOut) { Py_INCREF(pyOut); return pyOut; } - return converter->copyToPython(cppIn); + return converter->pointerToPython(cppIn); } static inline PyObject* CopyCppToPython(SbkConverter* converter, const void* cppIn) @@ -245,6 +240,8 @@ void nonePythonToCppNullPtr(PyObject*, void* cppOut) void* cppPointer(PyTypeObject* desiredType, SbkObject* pyIn) { assert(pyIn); + if (!ObjectType::checkType(desiredType)) + return pyIn; SbkObjectType* inType = (SbkObjectType*)Py_TYPE(pyIn); if (ObjectType::hasCast(inType)) return ObjectType::cast(inType, pyIn, desiredType); @@ -314,15 +311,12 @@ bool isImplicitConversion(SbkObjectType* type, PythonToCppFunc toCppFunc) void registerConverterName(SbkConverter* converter , const char* typeName) { ConvertersMap::iterator iter = converters.find(typeName); - if (iter == converters.end()) { - //SbkDbg() << "Registering " << typeName; + if (iter == converters.end()) converters.insert(std::make_pair(typeName, converter)); - } } SbkConverter* getConverter(const char* typeName) { - //SbkDbg() << "Looking for converter for type " << typeName; ConvertersMap::const_iterator it = converters.find(typeName); if (it != converters.end()) return it->second; @@ -480,4 +474,53 @@ bool pythonTypeIsObjectType(SbkConverter* converter) return converter->pointerToPython && !converter->copyToPython; } +SpecificConverter::SpecificConverter(const char* typeName) + : m_type(InvalidConversion) +{ + m_converter = getConverter(typeName); + if (!m_converter) + return; + int len = strlen(typeName); + char lastChar = typeName[len -1]; + if (lastChar == '&') { + m_type = ReferenceConversion; + } else if (lastChar == '*' || pythonTypeIsObjectType(m_converter)) { + m_type = PointerConversion; + } else { + m_type = CopyConversion; + } +} + +PyObject* SpecificConverter::toPython(const void* cppIn) +{ + switch (m_type) { + case CopyConversion: + return copyToPython(m_converter, cppIn); + case PointerConversion: + return pointerToPython(m_converter, *((const void**)cppIn)); + case ReferenceConversion: + return referenceToPython(m_converter, cppIn); + default: + PyErr_SetString(PyExc_RuntimeError, "tried to use invalid converter in 'C++ to Python' conversion"); + } + return 0; +} + +void SpecificConverter::toCpp(PyObject* pyIn, void* cppOut) +{ + switch (m_type) { + case CopyConversion: + pythonToCppCopy(m_converter, pyIn, cppOut); + break; + case PointerConversion: + pythonToCppPointer(m_converter, pyIn, cppOut); + break; + case ReferenceConversion: + pythonToCppPointer(m_converter, pyIn, &cppOut); + break; + default: + PyErr_SetString(PyExc_RuntimeError, "tried to use invalid converter in 'Python to C++' conversion"); + } +} + } } // namespace Shiboken::Conversions diff --git a/libshiboken/sbkconverter.h b/libshiboken/sbkconverter.h index a5b8d113..41126786 100644 --- a/libshiboken/sbkconverter.h +++ b/libshiboken/sbkconverter.h @@ -36,8 +36,6 @@ #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" { @@ -88,6 +86,36 @@ typedef PythonToCppFunc (*IsConvertibleToCppFunc)(PyObject*); namespace Shiboken { namespace Conversions { + +class LIBSHIBOKEN_API SpecificConverter +{ +public: + enum Type + { + InvalidConversion, + CopyConversion, + PointerConversion, + ReferenceConversion + }; + + explicit SpecificConverter(const char* typeName); + + inline SbkConverter* converter() { return m_converter; } + inline operator SbkConverter*() const { return m_converter; } + + inline bool isValid() { return m_type != InvalidConversion; } + inline operator bool() const { return m_type != InvalidConversion; } + + inline Type conversionType() { return m_type; } + + PyObject* toPython(const void* cppIn); + void toCpp(PyObject* pyIn, void* cppOut); +private: + SbkConverter* m_converter; + Type m_type; +}; + + /** * Creates a converter for a wrapper type. * \param type A Shiboken.ObjectType that will receive the new converter. @@ -306,4 +334,5 @@ template<> inline SbkConverter* PrimitiveTypeConverter() { return primiti struct _SbkGenericType { PyHeapTypeObject super; SbkConverter** converter; }; #define SBK_CONVERTER(pyType) (*reinterpret_cast<_SbkGenericType*>(pyType)->converter) + #endif // SBK_CONVERTER_H -- cgit v1.2.3