summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRenato Araujo Oliveira Filho <renato.filho@openbossa.org>2010-11-18 10:54:10 -0300
committerRenato Araujo Oliveira Filho <renato.filho@openbossa.org>2010-11-19 14:58:22 -0300
commite1ea3fe74afca099e7bba884256e0be0e6f7d200 (patch)
treebde6a3b3d38248b64edd6f13e5f84cbee0aa82fc
parent76c2a25f4def623be9c4ab30f2bde36bfed7ae08 (diff)
downloadshiboken-e1ea3fe74afca099e7bba884256e0be0e6f7d200.tar.gz
shiboken-e1ea3fe74afca099e7bba884256e0be0e6f7d200.tar.xz
shiboken-e1ea3fe74afca099e7bba884256e0be0e6f7d200.zip
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>
-rw-r--r--generator/cppgenerator.cpp29
-rw-r--r--libshiboken/basewrapper.cpp408
-rw-r--r--libshiboken/basewrapper.h63
-rw-r--r--libshiboken/basewrapper_p.h8
-rw-r--r--libshiboken/bindingmanager.cpp91
-rw-r--r--libshiboken/bindingmanager.h15
6 files changed, 349 insertions, 265 deletions
diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp
index 25584ce3..239bd753 100644
--- a/generator/cppgenerator.cpp
+++ b/generator/cppgenerator.cpp
@@ -470,7 +470,8 @@ void CppGenerator::writeDestructorNative(QTextStream &s, const AbstractMetaClass
{
Indentation indentation(INDENT);
s << wrapperName(metaClass) << "::~" << wrapperName(metaClass) << "()" << endl << '{' << endl;
- s << INDENT << "BindingManager::instance().destroyWrapper(this);" << endl;
+ s << INDENT << "SbkObject* wrapper = BindingManager::instance().retrieveWrapper(this);" << endl;
+ s << INDENT << "Wrapper::destroy(wrapper);" << endl;
s << '}' << endl;
}
@@ -523,6 +524,14 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu
return;
}
+ //Write declaration/native injected code
+ if (func->hasInjectedCode()) {
+ CodeSnipList snips = func->injectedCodeSnips();
+ const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last();
+ writeCodeSnips(s, snips, CodeSnip::Declaration, TypeSystem::NativeCode, func, lastArg);
+ s << endl;
+ }
+
s << INDENT << "Shiboken::GilState gil;" << endl;
s << INDENT << "Shiboken::AutoDecRef py_override(BindingManager::instance().getOverride(this, \"";
@@ -542,7 +551,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu
if (func->isAbstract()) {
s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"pure virtual method '";
s << func->ownerClass()->name() << '.' << func->name();
- s << "()' not implemented.\");" << endl;
+ s << "()' not implemented.\");" << endl;
s << INDENT << "return ";
if (func->type()) {
s << defaultReturnExpr;
@@ -731,7 +740,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu
if (invalidateReturn) {
s << INDENT << "if (invalidadeArg0)" << endl;
Indentation indentation(INDENT);
- s << INDENT << "BindingManager::instance().invalidateWrapper(" << PYTHON_RETURN_VAR ".object());" << endl;
+ s << INDENT << "Wrapper::invalidate(" << PYTHON_RETURN_VAR ".object());" << endl;
}
foreach (FunctionModification funcMod, func->modifications()) {
@@ -739,7 +748,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu
if (argMod.resetAfterUse) {
s << INDENT << "if (invalidadeArg" << argMod.index << ")" << endl;
Indentation indentation(INDENT);
- s << INDENT << "BindingManager::instance().invalidateWrapper(PyTuple_GET_ITEM(pyargs, ";
+ s << INDENT << "Wrapper::invalidate(PyTuple_GET_ITEM(pyargs, ";
s << (argMod.index - 1) << "));" << endl;
}
}
@@ -2121,15 +2130,15 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f
s << INDENT;
if (arg_mod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::TargetLangOwnership) {
- s << "Shiboken::Wrapper::getOwnership(" << pyArgName << ");";
+ s << "Wrapper::getOwnership(" << pyArgName << ");";
} else if (wrappedClass->hasVirtualDestructor()) {
if (arg_mod.index == 0) {
- s << "Shiboken::Wrapper::releaseOwnership(" PYTHON_RETURN_VAR ");";
+ s << "Wrapper::releaseOwnership(" PYTHON_RETURN_VAR ");";
} else {
- s << "BindingManager::instance().transferOwnershipToCpp(" << pyArgName << ");";
+ s << "Wrapper::releaseOwnership(" << pyArgName << ");";
}
} else {
- s << "BindingManager::instance().invalidateWrapper(" << pyArgName << ");";
+ s << "Wrapper::invalidate(" << pyArgName << ");";
}
s << endl;
}
@@ -3798,7 +3807,7 @@ bool CppGenerator::writeParentChildManagement(QTextStream& s, const AbstractMeta
else
childVariable = usePyArgs ? "pyargs["+QString::number(childIndex-1)+"]" : "arg";
- s << INDENT << "Shiboken::setParent(" << parentVariable << ", " << childVariable << ");\n";
+ s << INDENT << "Wrapper::setParent(" << parentVariable << ", " << childVariable << ");\n";
return true;
}
@@ -3832,7 +3841,7 @@ void CppGenerator::writeReturnValueHeuristics(QTextStream& s, const AbstractMeta
}
if (type->isQObject() || type->isObject() || type->isValuePointer())
- s << INDENT << "Shiboken::setParent(" << self << ", " PYTHON_RETURN_VAR ");" << endl;
+ s << INDENT << "Wrapper::setParent(" << self << ", " PYTHON_RETURN_VAR ");" << endl;
}
void CppGenerator::writeHashFunction(QTextStream& s, const AbstractMetaClass* metaClass)
diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp
index 47ec2749..37d1282a 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 98b9a4e0..f723a7a9 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 6cd4b31f..748ce2dc 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 183c0c05..b56cceed 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 c1926e5e..b6d4ac42 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();