diff options
author | Renato Araujo Oliveira Filho <renato.filho@openbossa.org> | 2010-11-18 10:54:10 -0300 |
---|---|---|
committer | Hugo Parente Lima <hugo.pl@gmail.com> | 2012-03-08 16:08:58 -0300 |
commit | 7e98252ba8e0d2fc72fc569b3ceb82662297ac9d (patch) | |
tree | 6d98c9c36b620f8abc4dbcbbdc1552f6c90b398d /libshiboken | |
parent | 31e6de8c9f237b1902be88baedf91ec9766bce87 (diff) |
Rewrite parent control functions.
Updated generator to new API.
Fix bug #462
Reviewer: Luciano Wolf <luciano.wolf@openbossa.org>
Hugo Parente Lima <hugo.pl@gmail.com>
Diffstat (limited to 'libshiboken')
-rw-r--r-- | libshiboken/basewrapper.cpp | 408 | ||||
-rw-r--r-- | libshiboken/basewrapper.h | 63 | ||||
-rw-r--r-- | libshiboken/basewrapper_p.h | 8 | ||||
-rw-r--r-- | libshiboken/bindingmanager.cpp | 91 | ||||
-rw-r--r-- | libshiboken/bindingmanager.h | 15 |
5 files changed, 330 insertions, 255 deletions
diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 47ec27492..37d1282a2 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -23,12 +23,13 @@ #include "basewrapper.h" #include "basewrapper_p.h" #include "sbkenum.h" -#include <cstddef> -#include <algorithm> #include "autodecref.h" #include "typeresolver.h" +#include "gilstate.h" #include <string> #include <cstring> +#include <cstddef> +#include <algorithm> extern "C" { @@ -163,8 +164,8 @@ void SbkDeallocWrapper(PyObject* pyObj) if (sbkObj->weakreflist) PyObject_ClearWeakRefs(pyObj); - Shiboken::BindingManager::instance().releaseWrapper(sbkObj); - if (sbkObj->d->hasOwnership) { + // If I have ownership and is valid delete C++ pointer + if (sbkObj->d->hasOwnership && sbkObj->d->validCppObject) { SbkObjectType* sbkType = reinterpret_cast<SbkObjectType*>(pyObj->ob_type); if (sbkType->is_multicpp) { Shiboken::DtorCallerVisitor visitor(sbkObj); @@ -174,26 +175,17 @@ void SbkDeallocWrapper(PyObject* pyObj) } } - if (sbkObj->d->parentInfo) - Shiboken::destroyParentInfo(sbkObj); - - Shiboken::clearReferences(sbkObj); - - Py_XDECREF(sbkObj->ob_dict); - delete[] sbkObj->d->cptr; - sbkObj->d->cptr = 0; - delete sbkObj->d; - Py_TYPE(pyObj)->tp_free(pyObj); + Shiboken::Wrapper::deallocData(sbkObj); } void SbkDeallocWrapperWithPrivateDtor(PyObject* self) { - if (((SbkObject *)self)->weakreflist) + SbkObject* sbkObj = reinterpret_cast<SbkObject*>(self); + if (sbkObj->weakreflist) PyObject_ClearWeakRefs(self); - Shiboken::BindingManager::instance().releaseWrapper(reinterpret_cast<SbkObject*>(self)); - Shiboken::clearReferences(reinterpret_cast<SbkObject*>(self)); - self->ob_type->tp_free(self); + Shiboken::BindingManager::instance().releaseWrapper(sbkObj); + Shiboken::Wrapper::deallocData(sbkObj); } void SbkObjectTypeDealloc(PyObject* pyObj) @@ -275,111 +267,6 @@ namespace Shiboken static void incRefPyObject(PyObject* pyObj); static void decRefPyObjectList(const std::list<SbkObject*> &pyObj); -void removeParent(SbkObject* child) -{ - ParentInfo* pInfo = child->d->parentInfo; - if (!pInfo || !pInfo->parent) - return; - - ChildrenList& oldBrothers = pInfo->parent->d->parentInfo->children; - oldBrothers.remove(child); - pInfo->parent = 0; - - if (pInfo->hasWrapperRef) { - Py_DECREF(child); - pInfo->hasWrapperRef = false; - } - Py_DECREF(child); -} - -void setParent(PyObject* parent, PyObject* child) -{ - if (!child || child == Py_None || child == parent) - return; - - /* - * setParent is recursive when the child is a native Python sequence, i.e. objects not binded by Shiboken - * like tuple and list. - * - * This "limitation" exists to fix the following problem: A class multiple inherits QObject and QString, - * so if you pass this class to someone that takes the ownership, we CAN'T enter in this if, but hey! QString - * follows the sequence protocol. - */ - if (PySequence_Check(child) && !isShibokenType(child)) { - Shiboken::AutoDecRef seq(PySequence_Fast(child, 0)); - for (int i = 0, max = PySequence_Size(seq); i < max; ++i) - setParent(parent, PySequence_Fast_GET_ITEM(seq.object(), i)); - return; - } - - bool parentIsNull = !parent || parent == Py_None; - SbkObject* parent_ = reinterpret_cast<SbkObject*>(parent); - SbkObject* child_ = reinterpret_cast<SbkObject*>(child); - - if (!parentIsNull) { - if (!parent_->d->parentInfo) - parent_->d->parentInfo = new ParentInfo; - // do not re-add a child - ChildrenList& children = parent_->d->parentInfo->children; - if (std::find(children.begin(), children.end(), child_) != children.end()) - return; - } - - ParentInfo* pInfo = child_->d->parentInfo; - bool hasAnotherParent = pInfo && pInfo->parent && pInfo->parent != parent_; - - //Avoid destroy child during reparent operation - Py_INCREF(child); - - // check if we need to remove this child from the old parent - if (parentIsNull || hasAnotherParent) - removeParent(child_); - - // Add the child to the new parent - pInfo = child_->d->parentInfo; - if (!parentIsNull) { - if (!pInfo) - pInfo = child_->d->parentInfo = new ParentInfo; - pInfo->parent = parent_; - parent_->d->parentInfo->children.push_back(child_); - Py_INCREF(child_); - } - - Py_DECREF(child); -} - -static void _destroyParentInfo(SbkObject* obj, bool removeFromParent) -{ - ParentInfo* pInfo = obj->d->parentInfo; - if (removeFromParent && pInfo && pInfo->parent) - removeParent(obj); - - if (pInfo) { - ChildrenList::iterator it = pInfo->children.begin(); - for (; it != pInfo->children.end(); ++it) { - SbkObject*& child = *it; - - // keep this, the wrapper still alive - if (!obj->d->containsCppWrapper && child->d->containsCppWrapper && child->d->parentInfo) { - child->d->parentInfo->parent = 0; - child->d->parentInfo->hasWrapperRef = true; - child->d->hasOwnership = false; - } else { - _destroyParentInfo(child, false); - Py_DECREF(child); - } - } - delete pInfo; - obj->d->parentInfo = 0; - } -} - -void destroyParentInfo(SbkObject* obj, bool removeFromParent) -{ - BindingManager::instance().destroyWrapper(obj); - _destroyParentInfo(obj, removeFromParent); -} - void walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visitor) { PyObject* bases = currentType->tp_bases; @@ -611,20 +498,45 @@ static void decRefPyObjectList(const std::list<SbkObject*>& lst) } } +namespace Wrapper +{ + static void setSequenceOwnership(PyObject* pyObj, bool owner) { if (PySequence_Check(pyObj)) { std::list<SbkObject*> objs = splitPyObject(pyObj); std::list<SbkObject*>::const_iterator it = objs.begin(); - for(; it != objs.end(); ++it) - (*it)->d->hasOwnership = owner; + for(; it != objs.end(); ++it) { + if (owner) + getOwnership(*it); + else + releaseOwnership(*it); + } } else if (isShibokenType(pyObj)) { - reinterpret_cast<SbkObject*>(pyObj)->d->hasOwnership = owner; + if (owner) + getOwnership(reinterpret_cast<SbkObject*>(pyObj)); + else + releaseOwnership(reinterpret_cast<SbkObject*>(pyObj)); } } -namespace Wrapper + +static void _destroyParentInfo(SbkObject* obj, bool keepReference) { + ParentInfo* pInfo = obj->d->parentInfo; + if (pInfo) { + while(!pInfo->children.empty()) { + SbkObject* first = pInfo->children.front(); + // Mark child as invalid + Shiboken::Wrapper::invalidate(first); + removeParent(first, false, keepReference); + } + removeParent(obj, false); + delete pInfo; + obj->d->parentInfo = 0; + } +} + void setValidCpp(SbkObject* pyObj, bool value) { @@ -646,9 +558,23 @@ bool hasOwnership(SbkObject* pyObj) return pyObj->d->hasOwnership; } -void getOwnership(SbkObject* pyObj) +void getOwnership(SbkObject* self) { - pyObj->d->hasOwnership = true; + // skip if already have the ownership + if (self->d->hasOwnership) + return; + + // skip if this object has parent + if (self->d->parentInfo && self->d->parentInfo->parent) + return; + + // Get back the ownership + self->d->hasOwnership = true; + + if (self->d->containsCppWrapper) + Py_DECREF((PyObject*) self); // Remove extra ref + else + makeValid(self); // Make the object valid again } void getOwnership(PyObject* pyObj) @@ -656,14 +582,78 @@ void getOwnership(PyObject* pyObj) setSequenceOwnership(pyObj, true); } -void releaseOwnership(SbkObject* pyObj) +void releaseOwnership(SbkObject* self) +{ + // skip if the ownership have already moved to c++ + if (!self->d->hasOwnership) + return; + + // remove object ownership + self->d->hasOwnership = false; + + // If We have control over object life + if (self->d->containsCppWrapper) + Py_INCREF((PyObject*) self); // keep the python object alive until the wrapper destructor call + else + invalidate(self); // If I do not know when this object will die We need to invalidate this to avoid use after +} + +void releaseOwnership(PyObject* self) +{ + setSequenceOwnership(self, false); +} + +void invalidate(PyObject* pyobj) { - pyObj->d->hasOwnership = false; + std::list<SbkObject*> objs = splitPyObject(pyobj); + std::list<SbkObject*>::const_iterator it = objs.begin(); + for(; it != objs.end(); it++) + invalidate(*it); } -void releaseOwnership(PyObject* pyObj) +void invalidate(SbkObject* self) { - setSequenceOwnership(pyObj, false); + // Skip if this object not is a valid object + if (!self || ((PyObject*)self == Py_None)) + return; + + if (!self->d->containsCppWrapper) { + self->d->validCppObject = false; // Mark object as invalid only if this is not a wrapper class + BindingManager::instance().releaseWrapper(self); + } + + // If it is a parent invalidate all children. + if (self->d->parentInfo) { + // Create a copy because this list can be changed during the process + ChildrenList copy = self->d->parentInfo->children; + ChildrenList::iterator it = copy.begin(); + + for (; it != copy.end(); ++it) { + // invalidate the child + invalidate(*it); + + // if the parent not is a wrapper class, then remove children from him, because We do not know when this object will be destroyed + if (!self->d->validCppObject) + removeParent(*it, true, true); + } + } +} + +void makeValid(SbkObject* self) +{ + // Skip if this object not is a valid object + if (!self || ((PyObject*)self == Py_None)) + return; + + // Mark object as invalid only if this is not a wrapper class + self->d->validCppObject = true; + + // If it is a parent make all children valid + if (self->d->parentInfo) { + ChildrenList::iterator it = self->d->parentInfo->children.begin(); + for (; it != self->d->parentInfo->children.end(); ++it) + makeValid(*it); + } } bool hasParentInfo(SbkObject* pyObj) @@ -732,6 +722,158 @@ PyObject* newObject(SbkObjectType* instanceType, return reinterpret_cast<PyObject*>(self); } +void destroy(SbkObject* self) +{ + // Skip if this is called with NULL pointer this can happen in derived classes + if (!self) + return; + + // This can be called in c++ side + Shiboken::GilState gil; + + // We will marks this object as invalid because this function will be called from wrapper destructor + // If The object has ownership and this was destroyed then is necessary invalidate to avoid future used by Python + self->d->validCppObject = false; + + // Remove all references attached to this object + clearReferences(self); + + // Remove from BindinManager + Shiboken::BindingManager::instance().releaseWrapper(self); + + // Remove the object from parent control + + // Verify if this object has parent + bool hasParent = (self->d->parentInfo && self->d->parentInfo->parent); + + if (self->d->parentInfo) { + // Check for children information and make all invalid if they exists + _destroyParentInfo(self, true); + // If this object has parent then the pyobject can be invalid now, because we remove the last ref after remove from parent + } + + //if !hasParent this object could still alive + if (!hasParent && self->d->containsCppWrapper && !self->d->hasOwnership) { + // Remove extra ref used by c++ object this will case the pyobject destruction + // This can cause the object death + Py_DECREF((PyObject*)self); + } + // After this point the object can be death do not use the self pointer bellow +} + +void removeParent(SbkObject* child, bool giveOwnershipBack, bool keepReference) +{ + ParentInfo* pInfo = child->d->parentInfo; + if (!pInfo || !pInfo->parent) { + return; + } + + ChildrenList& oldBrothers = pInfo->parent->d->parentInfo->children; + // Verify if this child is part of parent list + ChildrenList::iterator iChild = std::find(oldBrothers.begin(), oldBrothers.end(), child); + if (iChild == oldBrothers.end()) + return; + + oldBrothers.erase(iChild); + + pInfo->parent = 0; + + // This will keep the wrapper reference, will wait for wrapper destruction to remove that + if (keepReference && child->d->containsCppWrapper) + return; + + // Transfer ownership back to Python + child->d->hasOwnership = giveOwnershipBack; + + // Remove parent ref + Py_DECREF(child); +} + +void setParent(PyObject* parent, PyObject* child) +{ + if (!child || child == Py_None || child == parent) + return; + + /* + * setParent is recursive when the child is a native Python sequence, i.e. objects not binded by Shiboken + * like tuple and list. + * + * This "limitation" exists to fix the following problem: A class multiple inherits QObject and QString, + * so if you pass this class to someone that takes the ownership, we CAN'T enter in this if, but hey! QString + * follows the sequence protocol. + */ + if (PySequence_Check(child) && !isShibokenType(child)) { + Shiboken::AutoDecRef seq(PySequence_Fast(child, 0)); + for (int i = 0, max = PySequence_Size(seq); i < max; ++i) + setParent(parent, PySequence_Fast_GET_ITEM(seq.object(), i)); + return; + } + + bool parentIsNull = !parent || parent == Py_None; + SbkObject* parent_ = reinterpret_cast<SbkObject*>(parent); + SbkObject* child_ = reinterpret_cast<SbkObject*>(child); + + if (!parentIsNull) { + if (!parent_->d->parentInfo) + parent_->d->parentInfo = new ParentInfo; + // do not re-add a child + ChildrenList& children = parent_->d->parentInfo->children; + if (std::find(children.begin(), children.end(), child_) != children.end()) + return; + } + + ParentInfo* pInfo = child_->d->parentInfo; + bool hasAnotherParent = pInfo && pInfo->parent && pInfo->parent != parent_; + + //Avoid destroy child during reparent operation + Py_INCREF(child); + + // check if we need to remove this child from the old parent + if (parentIsNull || hasAnotherParent) + removeParent(child_); + + // Add the child to the new parent + pInfo = child_->d->parentInfo; + if (!parentIsNull) { + if (!pInfo) + pInfo = child_->d->parentInfo = new ParentInfo; + + pInfo->parent = parent_; + parent_->d->parentInfo->children.push_back(child_); + + // Add Parent ref + Py_INCREF(child_); + + // Remove ownership + child_->d->hasOwnership = false; + } + + // Remove previous safe ref + Py_DECREF(child); +} + +void deallocData(SbkObject* self) +{ + // Make cleanup if this is not a wrapper otherwise this will be done on wrapper destructor + if(!self->d->containsCppWrapper) { + removeParent(self); + + if (self->d->parentInfo) + _destroyParentInfo(self, true); + + clearReferences(self); + + // Remove from BindinManager + Shiboken::BindingManager::instance().releaseWrapper(self); + } + + Py_XDECREF(self->ob_dict); + delete[] self->d->cptr; + self->d->cptr = 0; + delete self->d; + Py_TYPE(self)->tp_free(self); +} + } // namespace Wrapper } // namespace Shiboken diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 98b9a4e0a..f723a7a9b 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -114,26 +114,6 @@ namespace Shiboken LIBSHIBOKEN_API void initShiboken(); /** -* Set the parent of \p child to \p parent. -* When an object dies, all their children, granchildren, etc, are tagged as invalid. -* \param parent the parent object, if null, the child will have no parents. -* \param child the child. -*/ -LIBSHIBOKEN_API void setParent(PyObject* parent, PyObject* child); - -/** -* Remove this child from their parent, if any. -* \param child the child. -*/ -LIBSHIBOKEN_API void removeParent(SbkObject* child); - -/** -* \internal This is an internal function called by SbkBaseWrapper_Dealloc, it's exported just for techinical reasons. -* \note Do not call this function inside your bindings. -*/ -LIBSHIBOKEN_API void destroyParentInfo(SbkObject* obj, bool removeFromParent = true); - -/** * Returns true if the object is an instance of a type created by the Shiboken generator. */ inline bool isShibokenType(PyObject*& pyObj) @@ -215,9 +195,50 @@ LIBSHIBOKEN_API void* cppPointer(SbkObject* pyObj, PyTypeObject* desiredType); */ LIBSHIBOKEN_API bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desiredType, void* cptr); -/// Returns false and sets a Python RuntimeError if the Python wrapper is not marked as valid. +/** + * Returns false and sets a Python RuntimeError if the Python wrapper is not marked as valid. + */ LIBSHIBOKEN_API bool isValid(PyObject* wrapper); +/** +* Set the parent of \p child to \p parent. +* When an object dies, all their children, granchildren, etc, are tagged as invalid. +* \param parent the parent object, if null, the child will have no parents. +* \param child the child. +*/ +LIBSHIBOKEN_API void setParent(PyObject* parent, PyObject* child); + +/** +* Remove this child from their parent, if any. +* \param child the child. +*/ +LIBSHIBOKEN_API void removeParent(SbkObject* child, bool giveOwnershipBack = true, bool keepReferenc = false); + +/** +* \internal This is an internal function called by SbkBaseWrapper_Dealloc, it's exported just for techinical reasons. +* \note Do not call this function inside your bindings. +*/ +LIBSHIBOKEN_API void destroyParentInfo(SbkObject* obj, bool removeFromParent = true); + +/** + * Mark the object as invalid + */ +LIBSHIBOKEN_API void invalidate(SbkObject* self); + +/** + * Help function can be used to invalida a sequence of object + **/ +LIBSHIBOKEN_API void invalidate(PyObject* pyobj); + +/** + * Make the object valid again + */ +LIBSHIBOKEN_API void makeValid(SbkObject* self); + +/** + * Destroy any data in Shiboken structure and c++ pointer if the pyboject has the ownership + **/ +LIBSHIBOKEN_API void destroy(SbkObject* self); } // namespace Wrapper diff --git a/libshiboken/basewrapper_p.h b/libshiboken/basewrapper_p.h index 6cd4b31f8..748ce2dca 100644 --- a/libshiboken/basewrapper_p.h +++ b/libshiboken/basewrapper_p.h @@ -196,6 +196,14 @@ inline std::list<SbkObjectType*> getCppBaseClasses(PyTypeObject* baseType) */ void clearReferences(SbkObject* self); +namespace Wrapper +{ +/** + * Destroy internal data + **/ +void deallocData(SbkObject* self); +} // namespace Wrapper + } // namespace Shiboken #endif diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp index 183c0c057..b56cceed4 100644 --- a/libshiboken/bindingmanager.cpp +++ b/libshiboken/bindingmanager.cpp @@ -147,8 +147,9 @@ BindingManager::~BindingManager() /* Cleanup hanging references. We just invalidate them as when * the BindingManager is being destroyed the interpreter is alredy * shutting down. */ - while (!m_d->wrapperMapper.empty()) - invalidateWrapper(m_d->wrapperMapper.begin()->second); + while (!m_d->wrapperMapper.empty()) { + Wrapper::destroy(m_d->wrapperMapper.begin()->second); + } assert(m_d->wrapperMapper.size() == 0); delete m_d; } @@ -162,6 +163,7 @@ bool BindingManager::hasWrapper(const void* cptr) { return m_d->wrapperMapper.count(cptr); } + void BindingManager::registerWrapper(SbkObject* pyObj, void* cptr) { SbkObjectType* instanceType = reinterpret_cast<SbkObjectType*>(pyObj->ob_type); @@ -248,91 +250,6 @@ PyObject* BindingManager::getOverride(const void* cptr, const char* methodName) return 0; } - -void BindingManager::invalidateWrapper(PyObject* pyobj) -{ - std::list<SbkObject*> objs = splitPyObject(pyobj); - std::list<SbkObject*>::const_iterator it = objs.begin(); - for(; it != objs.end(); it++) - invalidateWrapper(*it); -} - -void BindingManager::invalidateWrapper(SbkObject* wrapper) -{ - if (!wrapper || ((PyObject*)wrapper == Py_None) || !wrapper->d->validCppObject) - return; - - GilState gil; // lock the gil to assure no one is changing the value of m_d->destroying - - // skip this if the object is a wrapper class and this is not a destructor call - if (wrapper->d->containsCppWrapper && !m_d->destroying) { - ParentInfo* pInfo = wrapper->d->parentInfo; - // this meaning the object has a extra ref and we will remove this now - if (pInfo && pInfo->hasWrapperRef) { - delete pInfo; - wrapper->d->parentInfo = 0; - Py_XDECREF((PyObject*) wrapper); - } - return; - } - - wrapper->d->validCppObject = false; - wrapper->d->hasOwnership = false; - - // If it is a parent invalidate all children. - if (wrapper->d->parentInfo) { - ChildrenList::iterator it = wrapper->d->parentInfo->children.begin(); - bool parentDestroying = m_d->destroying; - m_d->destroying = false; - for (; it != wrapper->d->parentInfo->children.end(); ++it) - invalidateWrapper(*it); - m_d->destroying = parentDestroying; - } - - releaseWrapper(wrapper); -} - -void BindingManager::invalidateWrapper(const void* cptr) -{ - WrapperMap::iterator iter = m_d->wrapperMapper.find(cptr); - if (iter != m_d->wrapperMapper.end()) - invalidateWrapper(iter->second); -} - -void BindingManager::destroyWrapper(const void* cptr) -{ - WrapperMap::iterator iter = m_d->wrapperMapper.find(cptr); - if (iter != m_d->wrapperMapper.end()) - destroyWrapper(reinterpret_cast<SbkObject*>(iter->second)); -} - -void BindingManager::destroyWrapper(SbkObject* wrapper) -{ - GilState gil; - m_d->destroying = true; - invalidateWrapper(wrapper); - m_d->destroying = false; -} - -void BindingManager::transferOwnershipToCpp(PyObject* wrapper) -{ - std::list<SbkObject*> objs = splitPyObject(wrapper); - std::list<SbkObject*>::const_iterator it = objs.begin(); - for(; it != objs.end(); it++) - transferOwnershipToCpp(*it); -} - -void BindingManager::transferOwnershipToCpp(SbkObject* wrapper) -{ - if (wrapper->d->parentInfo) - Shiboken::removeParent(wrapper); - - if (wrapper->d->containsCppWrapper) - wrapper->d->hasOwnership = false; - else - invalidateWrapper(wrapper); -} - void BindingManager::addClassInheritance(SbkObjectType* parent, SbkObjectType* child) { m_d->classHierarchy.addEdge(parent, child); diff --git a/libshiboken/bindingmanager.h b/libshiboken/bindingmanager.h index c1926e5ee..b6d4ac42b 100644 --- a/libshiboken/bindingmanager.h +++ b/libshiboken/bindingmanager.h @@ -42,26 +42,13 @@ public: void registerWrapper(SbkObject* pyObj, void* cptr); void releaseWrapper(SbkObject* wrapper); + SbkObject* retrieveWrapper(const void* cptr); PyObject* getOverride(const void* cptr, const char* methodName); - /// Invalidate the Python wrapper and removes the relations from C++ pointers to the Python wrapper. - void invalidateWrapper(SbkObject* wrapper); - /// Convenience method to call invalidateWrapper with a properly cast SbkBaseWrapper. - void invalidateWrapper(PyObject* wrapper); - /// Convenience method to invalidate the Python wrapper for a C++ wrapped object. Do nothing if C++ pointer has no Python wrapper. - void invalidateWrapper(const void* cptr); - - /// Transfers the ownership of a Python wrapper to C++. - void transferOwnershipToCpp(SbkObject* wrapper); - /// Convenience method to call transferOwnershipToCpp with a properly cast SbkBaseWrapper. - void transferOwnershipToCpp(PyObject* wrapper); void addClassInheritance(SbkObjectType* parent, SbkObjectType* child); SbkObjectType* resolveType(void* cptr, SbkObjectType* type); - /// Called by wrapper destructor - void destroyWrapper(const void* cptr); - void destroyWrapper(SbkObject* wrapper); std::set<SbkObject*> getAllPyObjects(); private: ~BindingManager(); |