diff options
Diffstat (limited to 'libshiboken')
-rw-r--r-- | libshiboken/CMakeLists.txt | 1 | ||||
-rw-r--r-- | libshiboken/basewrapper.cpp | 20 | ||||
-rw-r--r-- | libshiboken/basewrapper.h | 4 | ||||
-rw-r--r-- | libshiboken/conversions.h | 8 | ||||
-rw-r--r-- | libshiboken/typeresolver.cpp | 125 | ||||
-rw-r--r-- | libshiboken/typeresolver.h | 113 |
6 files changed, 264 insertions, 7 deletions
diff --git a/libshiboken/CMakeLists.txt b/libshiboken/CMakeLists.txt index f36567d63..3cc0a5618 100644 --- a/libshiboken/CMakeLists.txt +++ b/libshiboken/CMakeLists.txt @@ -14,6 +14,7 @@ basewrapper.cpp helper.cpp pyenum.cpp bindingmanager.cpp +typeresolver.cpp ) include_directories(${CMAKE_CURRENT_SOURCE_DIR} diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index cad4efe0d..b0f1b9c0a 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -36,6 +36,7 @@ #include <cstddef> #include <algorithm> #include "autodecref.h" +#include "typeresolver.h" namespace Shiboken { @@ -109,12 +110,24 @@ void destroyParentInfo(SbkBaseWrapper* obj, bool removeFromParent) PyObject* SbkBaseWrapper_New(SbkBaseWrapperType* instanceType, const void* cptr, bool hasOwnership, - bool containsCppWrapper) + bool isExactType) { + // Try to find the exact type of cptr. + if (!isExactType && instanceType->type_name_func) { + const char* typeName = instanceType->type_name_func(cptr); + TypeResolver* typeResolver = TypeResolver::get(typeName); + if (typeResolver) + instanceType = reinterpret_cast<SbkBaseWrapperType*>(typeResolver->pythonType()); + #ifndef NDEBUG + else + fprintf(stderr, "[SHIBOKEN] Can't find type resolver for %s.\n", typeName); + #endif + } + SbkBaseWrapper* self = reinterpret_cast<SbkBaseWrapper*>(SbkBaseWrapper_TpNew(reinterpret_cast<PyTypeObject*>(instanceType), 0, 0)); self->cptr = const_cast<void*>(cptr); self->hasOwnership = hasOwnership; - self->containsCppWrapper = containsCppWrapper; + self->containsCppWrapper = 0; self->validCppObject = 1; self->parentInfo = 0; BindingManager::instance().registerWrapper(self); @@ -253,7 +266,8 @@ SbkBaseWrapperType SbkBaseWrapper_Type = { { { }, }, /*mi_offsets*/ 0, /*mi_init*/ 0, -/*mi_specialcast*/ 0 +/*mi_specialcast*/ 0, +/*type_name_func*/ 0 }; PyAPI_FUNC(void) init_shiboken() diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 7de5f9086..38e0a0c48 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -69,6 +69,7 @@ struct SbkBaseWrapperType; * The implementation of this function is auto generated by the generator and you don't need to care about it. */ typedef void* (*SpecialCastFunction)(PyObject*, SbkBaseWrapperType*); +typedef const char* (*TypeNameFunction)(const void*); LIBSHIBOKEN_API PyAPI_DATA(PyTypeObject) SbkBaseWrapperType_Type; LIBSHIBOKEN_API PyAPI_DATA(SbkBaseWrapperType) SbkBaseWrapper_Type; @@ -81,6 +82,7 @@ struct LIBSHIBOKEN_API SbkBaseWrapperType MultipleInheritanceInitFunction mi_init; /// Special cast function, null if this class doesn't have multiple inheritance. SpecialCastFunction mi_specialcast; + TypeNameFunction type_name_func; }; /// Base Python object for all the wrapped C++ classes. @@ -194,7 +196,7 @@ LIBSHIBOKEN_API PyAPI_FUNC(PyObject*) SbkBaseWrapper_New(SbkBaseWrapperType* instanceType, const void* cptr, bool hasOwnership = true, - bool containsCppWrapper = false); + bool isExactType = false); LIBSHIBOKEN_API PyAPI_FUNC(PyObject*) SbkBaseWrapper_TpNew(PyTypeObject* subtype, PyObject*, PyObject*); diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index 1dc00b00f..e3b2ac34b 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -89,10 +89,10 @@ struct CppObjectCopier * Convenience template to create wrappers using the proper Python type for a given C++ class instance. */ template<typename T> -inline PyObject* SbkCreateWrapper(const T* cppobj, bool hasOwnership = false, bool containsCppWrapper = false) +inline PyObject* SbkCreateWrapper(const T* cppobj, bool hasOwnership = false, bool isExactType = false) { return SbkBaseWrapper_New(reinterpret_cast<SbkBaseWrapperType*>(SbkType<T>()), - cppobj, hasOwnership, containsCppWrapper); + cppobj, hasOwnership, isExactType); } // Base Conversions ---------------------------------------------------------- @@ -105,7 +105,9 @@ struct ConverterBase static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<T*>(cppobj)); } static inline PyObject* toPython(const T& cppobj) { - return SbkCreateWrapper<T>(CppObjectCopier<T>::copy(cppobj), true, CppObjectCopier<T>::isCppWrapper); + PyObject* obj = SbkCreateWrapper<T>(CppObjectCopier<T>::copy(cppobj), true, true); + SbkBaseWrapper_setContainsCppWrapper(obj, CppObjectCopier<T>::isCppWrapper); + return obj; } // Classes with implicit conversions are expected to reimplement // this to build T from its various implicit constructors. diff --git a/libshiboken/typeresolver.cpp b/libshiboken/typeresolver.cpp new file mode 100644 index 000000000..3ed3daf67 --- /dev/null +++ b/libshiboken/typeresolver.cpp @@ -0,0 +1,125 @@ +/* + * This file is part of the Shiboken Python Bindings Generator project. + * + * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team <contact@pyside.org> + * + * 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 + */ + +#include "typeresolver.h" +#include "google/dense_hash_map" +#include <cstdlib> + +using namespace Shiboken; + +typedef google::dense_hash_map<std::string, TypeResolver*> TypeResolverMap; +static TypeResolverMap typeResolverMap; + +struct TypeResolver::TypeResolverPrivate +{ + const char* typeName; // maybe this is not needed anymore + CppToPythonFunc cppToPython; + PythonToCppFunc pythonToCpp; + DeleteObjectFunc deleteObject; + GetPyTypeFunc getPyType; +}; + +static void deinitTypeResolver() +{ + for (TypeResolverMap::const_iterator it = typeResolverMap.begin(); it != typeResolverMap.end(); ++it) + delete it->second; + typeResolverMap.clear(); +} + +static void registerTypeResolver(TypeResolver* resolver) +{ + static bool initied = false; + if (!initied) { + assert(typeResolverMap.empty()); + typeResolverMap.set_empty_key(""); + typeResolverMap.set_deleted_key("?"); + initied = true; + std::atexit(deinitTypeResolver); + TypeResolver::createValueTypeResolver<double>("double"); + TypeResolver::createValueTypeResolver<float>("float"); + TypeResolver::createValueTypeResolver<bool>("bool"); + TypeResolver::createValueTypeResolver<int>("int"); + } + assert(typeResolverMap.find(resolver->typeName()) == typeResolverMap.end()); + typeResolverMap[resolver->typeName()] = resolver; +} + +TypeResolver::TypeResolver(const char* typeName, TypeResolver::CppToPythonFunc cppToPy, TypeResolver::PythonToCppFunc pyToCpp, GetPyTypeFunc getPyType, TypeResolver::DeleteObjectFunc deleter) +{ + m_d = new TypeResolverPrivate; + m_d->typeName = typeName; + m_d->cppToPython = cppToPy; + m_d->pythonToCpp = pyToCpp; + m_d->deleteObject = deleter; + m_d->getPyType = getPyType; + + registerTypeResolver(this); +} + +TypeResolver::~TypeResolver() +{ + delete m_d; +} + +TypeResolver* TypeResolver::get(const char* typeName) +{ + TypeResolverMap::const_iterator it = typeResolverMap.find(typeName); + return it == typeResolverMap.end() ? 0 : it->second; +} + +const char* TypeResolver::typeName() const +{ + return m_d->typeName; +} + +void* TypeResolver::toCpp(PyObject* pyObj) +{ + return m_d->pythonToCpp(pyObj); +} + +PyObject* TypeResolver::toPython(void* cppObj) +{ + return m_d->cppToPython(cppObj); +} + +void TypeResolver::deleteObject(void* object) +{ + if (m_d->deleteObject) + m_d->deleteObject(object); +} + +PyTypeObject* TypeResolver::pythonType() +{ + return m_d->getPyType(); +} diff --git a/libshiboken/typeresolver.h b/libshiboken/typeresolver.h new file mode 100644 index 000000000..4e7efb81b --- /dev/null +++ b/libshiboken/typeresolver.h @@ -0,0 +1,113 @@ +/* + * This file is part of the Shiboken Python Bindings Generator project. + * + * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team <contact@pyside.org> + * + * 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 TYPERESOLVER_H +#define TYPERESOLVER_H + +#include "shibokenmacros.h" +#include "conversions.h" + +namespace Shiboken +{ + +class SbkBaseWrapperType; + +/* To C++ convertion functions. */ +template <typename T> +inline void* pythonToValueType(PyObject* pyobj) +{ + return Shiboken::CppObjectCopier<T>::copy(Shiboken::Converter<T>::toCpp(pyobj)); +} + +template <typename T> +inline void* pythonToObjectType(PyObject* pyobj) +{ + return Shiboken::Converter<T*>::toCpp(pyobj); +} + +template <typename T> +inline void objectDeleter(void* data) +{ + delete reinterpret_cast<T*>(data); +} + +template <typename T> +inline PyObject* objectTypeToPython(void* cptr) +{ + return Shiboken::Converter<T*>::toPython(*reinterpret_cast<T**>(cptr)); +} + +class LIBSHIBOKEN_API TypeResolver +{ +public: + typedef PyObject* (*CppToPythonFunc)(void*); + typedef void* (*PythonToCppFunc)(PyObject*); + typedef void (*DeleteObjectFunc)(void*); + typedef PyTypeObject* (*GetPyTypeFunc)(); + + ~TypeResolver(); + + template<typename T> + static TypeResolver* createValueTypeResolver(const char* typeName) + { + return new TypeResolver(typeName, &Shiboken::Converter<T>::toPython, &pythonToValueType<T>, &SbkType<T>, &objectDeleter<T>); + } + + template<typename T> + static TypeResolver* createObjectTypeResolver(const char* typeName) + { + return new TypeResolver(typeName, &objectTypeToPython<T>, &pythonToObjectType<T>, &SbkType<T>); + } + + static TypeResolver* get(const char* typeName); + + const char* typeName() const; + PyObject* toPython(void* cppObj); + void* toCpp(PyObject* pyObj); + void deleteObject(void* object); + PyTypeObject* pythonType(); + +private: + struct TypeResolverPrivate; + TypeResolverPrivate* m_d; + + // disable object copy + TypeResolver(const TypeResolver&); + TypeResolver& operator=(const TypeResolver&); + + TypeResolver(const char* typeName, CppToPythonFunc cppToPy, PythonToCppFunc pyToCpp, GetPyTypeFunc getPyType, DeleteObjectFunc deleter = 0); +}; +} + +#endif |