diff options
author | Hugo Parente Lima <hugo.pl@gmail.com> | 2011-08-04 16:10:34 -0300 |
---|---|---|
committer | Hugo Parente Lima <hugo.pl@gmail.com> | 2012-03-08 16:17:13 -0300 |
commit | 784a4bbb707d132b26bcb177521745575dc0823f (patch) | |
tree | f637ef4134445b1cfdd0c33878b7a1ce46f02145 /libshiboken | |
parent | 8b1ddcd3ef711bab70bb7cdebc26558a26f42df9 (diff) |
Implements PSEP-0106 and fixes bug 902 - "Expose Shiboken functionality through a Python module".
Diffstat (limited to 'libshiboken')
-rw-r--r-- | libshiboken/basewrapper.cpp | 96 | ||||
-rw-r--r-- | libshiboken/basewrapper.h | 27 | ||||
-rw-r--r-- | libshiboken/basewrapper_p.h | 13 |
3 files changed, 132 insertions, 4 deletions
diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index b5772e953..d41bfd15b 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -29,6 +29,8 @@ #include <string> #include <cstring> #include <cstddef> +#include <set> +#include <sstream> #include <algorithm> #include "threadstatesaver.h" @@ -180,7 +182,7 @@ void SbkDeallocWrapper(PyObject* pyObj) if (sbkObj->d->hasOwnership && sbkObj->d->validCppObject) { SbkObjectType* sbkType = reinterpret_cast<SbkObjectType*>(pyObj->ob_type); if (sbkType->d->is_multicpp) { - Shiboken::DtorCallerVisitor visitor(sbkObj); + Shiboken::DeallocVisitor visitor(sbkObj); Shiboken::walkThroughClassHierarchy(pyObj->ob_type, &visitor); } else { void* cptr = sbkObj->d->cptr[0]; @@ -387,8 +389,6 @@ void DtorCallerVisitor::visit(SbkObjectType* node) void DtorCallerVisitor::done() { - Shiboken::Object::deallocData(m_pyObj, true); - std::list<std::pair<void*, SbkObjectType*> >::const_iterator it = m_ptrs.begin(); for (; it != m_ptrs.end(); ++it) { Shiboken::ThreadStateSaver threadSaver; @@ -397,6 +397,12 @@ void DtorCallerVisitor::done() } } +void DeallocVisitor::done() +{ + Shiboken::Object::deallocData(m_pyObj, true); + DtorCallerVisitor::done(); +} + namespace Module { void init(); } void init() @@ -739,6 +745,27 @@ bool hasCppWrapper(SbkObject* pyObj) return pyObj->d->containsCppWrapper; } +bool wasCreatedByPython(SbkObject* pyObj) +{ + return pyObj->d->cppObjectCreated; +} + +void callCppDestructors(SbkObject* pyObj) +{ + SbkObjectType* sbkType = reinterpret_cast<SbkObjectType*>(pyObj->ob_type); + if (sbkType->d->is_multicpp) { + Shiboken::DtorCallerVisitor visitor(pyObj); + Shiboken::walkThroughClassHierarchy(pyObj->ob_type, &visitor); + } else { + Shiboken::ThreadStateSaver threadSaver; + threadSaver.save(); + sbkType->d->cpp_dtor(pyObj->d->cptr[0]); + } + delete[] pyObj->d->cptr; + pyObj->d->cptr = 0; + invalidate(pyObj); +} + bool hasOwnership(SbkObject* pyObj) { return pyObj->d->hasOwnership; @@ -860,6 +887,16 @@ void* cppPointer(SbkObject* pyObj, PyTypeObject* desiredType) return 0; } +std::vector<void*> cppPointers(SbkObject* pyObj) +{ + int n = getNumberOfCppBaseClasses(Py_TYPE(pyObj)); + std::vector<void*> ptrs(n); + for (int i = 0; i < n; ++i) + ptrs[i] = pyObj->d->cptr[i]; + return ptrs; +} + + bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desiredType, void* cptr) { int idx = 0; @@ -1215,6 +1252,59 @@ void clearReferences(SbkObject* self) self->d->referredObjects = 0; } +std::string info(SbkObject* self) +{ + std::ostringstream s; + std::list<SbkObjectType*> bases = getCppBaseClasses(self->ob_type); + + s << "C++ address....... "; + std::list<SbkObjectType*>::const_iterator it = bases.begin(); + for (int i = 0; it != bases.end(); ++it, ++i) + s << ((PyTypeObject*)*it)->tp_name << "/" << self->d->cptr[i] << ' '; + s << "\n"; + + s << "hasOwnership...... " << bool(self->d->hasOwnership) << "\n" + "containsCppWrapper " << self->d->containsCppWrapper << "\n" + "validCppObject.... " << self->d->validCppObject << "\n" + "wasCreatedByPython " << self->d->cppObjectCreated << "\n"; + + + if (self->d->parentInfo && self->d->parentInfo->parent) { + s << "parent............ "; + Shiboken::AutoDecRef parent(PyObject_Str((PyObject*)self->d->parentInfo->parent)); + s << PyString_AS_STRING(parent.object()) << "\n"; + } + + if (self->d->parentInfo && self->d->parentInfo->children.size()) { + s << "children.......... "; + ChildrenList& children = self->d->parentInfo->children; + for (ChildrenList::const_iterator it = children.begin(); it != children.end(); ++it) { + Shiboken::AutoDecRef child(PyObject_Str((PyObject*)*it)); + s << PyString_AS_STRING(child.object()) << ' '; + } + s << '\n'; + } + + if (self->d->referredObjects && self->d->referredObjects->size()) { + Shiboken::RefCountMap& map = *self->d->referredObjects; + s << "referred objects.. "; + Shiboken::RefCountMap::const_iterator it = map.begin(); + for (; it != map.end(); ++it) { + if (it != map.begin()) + s << " "; + s << '"' << it->first << "\" => "; + std::list<PyObject*>::const_iterator j = it->second.begin(); + for (; j != it->second.end(); ++j) { + Shiboken::AutoDecRef obj(PyObject_Str(*j)); + s << PyString_AS_STRING(obj.object()) << ' '; + } + s << ' '; + } + s << '\n'; + } + return s.str(); +} + } // namespace Object } // namespace Shiboken diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 3c6fa4f9e..334ac6caf 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -27,6 +27,7 @@ #include "python25compat.h" #include "bindingmanager.h" #include <list> +#include <vector> #include <map> #include <string> @@ -209,9 +210,15 @@ LIBSHIBOKEN_API void setTypeUserData(SbkObjectType* self, void* userData, namespace Object { /** + * Returns a string with information about the internal state of the instance object, useful for debug purposes. + */ +LIBSHIBOKEN_API std::string info(SbkObject* self); + +/** * Returns true if the object is an instance of a type created by the Shiboken generator. */ LIBSHIBOKEN_API bool checkType(PyObject* pyObj); + /** * Returns true if this object type is an instance of an user defined type derived from an Shiboken type. * \see Shiboken::ObjectType::isUserType @@ -247,9 +254,22 @@ LIBSHIBOKEN_API void setHasCppWrapper(SbkObject* pyObj, bool value); LIBSHIBOKEN_API bool hasCppWrapper(SbkObject* pyObj); /** + * Return true if the Python object was created by Python, false otherwise. + * \note This function was added to libshiboken only to be used by shiboken.wasCreatedByPython() + */ +LIBSHIBOKEN_API bool wasCreatedByPython(SbkObject* pyObj); + +/** + * Call the C++ object destructor and invalidates the Python object. + * \note This function was added to libshiboken only to be used by shiboken.delete() + */ +LIBSHIBOKEN_API void callCppDestructors(SbkObject* pyObj); + +/** * Return true if the Python is responsible for deleting the underlying C++ object. */ LIBSHIBOKEN_API bool hasOwnership(SbkObject* pyObj); + /** * Sets python as responsible to delete the underlying C++ object. * \note You this overload only when the PyObject can be a sequence and you want to @@ -257,6 +277,7 @@ LIBSHIBOKEN_API bool hasOwnership(SbkObject* pyObj); * \see getOwnership(SbkObject*) */ LIBSHIBOKEN_API void getOwnership(PyObject* pyObj); + /** * Sets python as responsible to delete the underlying C++ object. */ @@ -285,6 +306,12 @@ LIBSHIBOKEN_API bool hasParentInfo(SbkObject* pyObj); LIBSHIBOKEN_API void* cppPointer(SbkObject* pyObj, PyTypeObject* desiredType); /** + * Return a list with all C++ pointers held from a Python object. + * \note This function was added to libshiboken only to be used by shiboken.getCppPointer() + */ +LIBSHIBOKEN_API std::vector<void*> cppPointers(SbkObject* pyObj); + +/** * Set the C++ pointer of type \p desiredType of a Python object. */ LIBSHIBOKEN_API bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desiredType, void* cptr); diff --git a/libshiboken/basewrapper_p.h b/libshiboken/basewrapper_p.h index 39b35f65d..35c9c83df 100644 --- a/libshiboken/basewrapper_p.h +++ b/libshiboken/basewrapper_p.h @@ -26,6 +26,8 @@ #include <Python.h> #include <list> #include <map> +#include <set> +#include <string> struct SbkObject; struct SbkObjectType; @@ -190,17 +192,26 @@ private: PyTypeObject* m_desiredType; }; +/// Call the destructor of each C++ object held by a Python object class DtorCallerVisitor : public HierarchyVisitor { public: DtorCallerVisitor(SbkObject* pyObj) : m_pyObj(pyObj) {} void visit(SbkObjectType* node); void done(); -private: +protected: std::list<std::pair<void*, SbkObjectType*> > m_ptrs; SbkObject* m_pyObj; }; +/// Dealloc of each C++ object held by a Python object, this implies a call to the C++ object destructor +class DeallocVisitor : public DtorCallerVisitor +{ +public: + DeallocVisitor(SbkObject* pyObj) : DtorCallerVisitor(pyObj) {} + void done(); +}; + /// \internal Internal function used to walk on classes inheritance trees. /** * Walk on class hierarchy using a DFS algorithm. |