aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generator/cppgenerator.cpp2
-rw-r--r--libshiboken/basewrapper.cpp24
-rw-r--r--libshiboken/basewrapper_p.h4
-rw-r--r--libshiboken/bindingmanager.cpp40
-rw-r--r--libshiboken/bindingmanager.h4
5 files changed, 69 insertions, 5 deletions
diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp
index 7f9c865ca..cd7f14eca 100644
--- a/generator/cppgenerator.cpp
+++ b/generator/cppgenerator.cpp
@@ -425,7 +425,7 @@ void CppGenerator::writeDestructorNative(QTextStream &s, const AbstractMetaClass
{
Indentation indentation(INDENT);
s << wrapperName(metaClass) << "::~" << wrapperName(metaClass) << "()" << endl << '{' << endl;
- s << INDENT << "BindingManager::instance().invalidateWrapper(this);" << endl;
+ s << INDENT << "BindingManager::instance().destroyWrapper(this);" << endl;
s << '}' << endl;
}
diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp
index 7f674c9c2..6e8848bbc 100644
--- a/libshiboken/basewrapper.cpp
+++ b/libshiboken/basewrapper.cpp
@@ -173,6 +173,11 @@ void removeParent(SbkBaseWrapper* child)
ChildrenList& oldBrothers = pInfo->parent->parentInfo->children;
oldBrothers.remove(child);
pInfo->parent = 0;
+
+ if (pInfo->hasWrapperRef) {
+ Py_DECREF(child);
+ pInfo->hasWrapperRef = false;
+ }
Py_DECREF(child);
}
@@ -220,6 +225,7 @@ void setParent(PyObject* parent, PyObject* child)
removeParent(child_);
// Add the child to the new parent
+ pInfo = child_->parentInfo;
if (!parentIsNull) {
if (!pInfo)
pInfo = child_->parentInfo = new ParentInfo;
@@ -236,11 +242,22 @@ static void _destroyParentInfo(SbkBaseWrapper* obj, bool removeFromParent)
ParentInfo* pInfo = obj->parentInfo;
if (removeFromParent && pInfo && pInfo->parent)
removeParent(obj);
+
ChildrenList::iterator it = pInfo->children.begin();
for (; it != pInfo->children.end(); ++it) {
SbkBaseWrapper*& child = *it;
- _destroyParentInfo(child, false);
- Py_DECREF(child);
+
+ // keep this, the wrapper still alive
+ if (!SbkBaseWrapper_containsCppWrapper(obj) &&
+ SbkBaseWrapper_containsCppWrapper(child) &&
+ child->parentInfo) {
+ child->parentInfo->parent = 0;
+ child->parentInfo->hasWrapperRef = true;
+ SbkBaseWrapper_setOwnership(child, false);
+ } else {
+ _destroyParentInfo(child, false);
+ Py_DECREF(child);
+ }
}
delete pInfo;
obj->parentInfo = 0;
@@ -248,7 +265,7 @@ static void _destroyParentInfo(SbkBaseWrapper* obj, bool removeFromParent)
void destroyParentInfo(SbkBaseWrapper* obj, bool removeFromParent)
{
- BindingManager::instance().invalidateWrapper(obj);
+ BindingManager::instance().destroyWrapper(obj);
_destroyParentInfo(obj, removeFromParent);
}
@@ -490,6 +507,7 @@ void deallocWrapper(PyObject* pyObj)
if (SbkBaseWrapper_hasParentInfo(pyObj))
destroyParentInfo(sbkObj);
+
clearReferences(sbkObj);
Py_XDECREF(sbkObj->ob_dict);
diff --git a/libshiboken/basewrapper_p.h b/libshiboken/basewrapper_p.h
index e1a9a0e73..1357c89a6 100644
--- a/libshiboken/basewrapper_p.h
+++ b/libshiboken/basewrapper_p.h
@@ -131,11 +131,13 @@ typedef std::list<SbkBaseWrapper*> ChildrenList;
struct ParentInfo
{
/// Default ctor.
- ParentInfo() : parent(0) {}
+ ParentInfo() : parent(0), hasWrapperRef(false) {}
/// Pointer to parent object.
SbkBaseWrapper* parent;
/// List of object children.
ChildrenList children;
+ /// has internal ref
+ bool hasWrapperRef;
};
/**
diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp
index 596e7ba01..47fd77d71 100644
--- a/libshiboken/bindingmanager.cpp
+++ b/libshiboken/bindingmanager.cpp
@@ -102,8 +102,12 @@ static void showWrapperMap(const WrapperMap& wrapperMap)
struct BindingManager::BindingManagerPrivate {
WrapperMap wrapperMapper;
Graph classHierarchy;
+ bool destroying;
+
+ BindingManagerPrivate() : destroying(false) {}
void releaseWrapper(void* cptr);
void assignWrapper(PyObject* wrapper, const void* cptr);
+
};
void BindingManager::BindingManagerPrivate::releaseWrapper(void* cptr)
@@ -245,14 +249,32 @@ void BindingManager::invalidateWrapper(SbkBaseWrapper* wrapper)
{
if (!wrapper || ((PyObject*)wrapper == Py_None) || !SbkBaseWrapper_validCppObject(wrapper))
return;
+
+ // skip this if the object is a wrapper class and this is not a destructor call
+ if (SbkBaseWrapper_containsCppWrapper(wrapper) && !m_d->destroying) {
+ ParentInfo* pInfo = wrapper->parentInfo;
+ // this meaning the object has a extra ref and we will remove this now
+ if (pInfo && pInfo->hasWrapperRef) {
+ delete pInfo;
+ wrapper->parentInfo = 0;
+ Py_XDECREF((PyObject*) wrapper);
+ }
+ return;
+ }
+
SbkBaseWrapper_setValidCppObject(wrapper, false);
SbkBaseWrapper_setOwnership(wrapper, false);
+
// If it is a parent invalidate all children.
if (SbkBaseWrapper_hasParentInfo(wrapper)) {
ChildrenList::iterator it = wrapper->parentInfo->children.begin();
+ bool parentDestroying = m_d->destroying;
+ m_d->destroying = false;
for (; it != wrapper->parentInfo->children.end(); ++it)
invalidateWrapper(*it);
+ m_d->destroying = parentDestroying;
}
+
releaseWrapper(reinterpret_cast<PyObject*>(wrapper));
}
@@ -263,6 +285,24 @@ void BindingManager::invalidateWrapper(const void* cptr)
invalidateWrapper(iter->second);
}
+void BindingManager::destroyWrapper(const void* cptr)
+{
+ WrapperMap::iterator iter = m_d->wrapperMapper.find(cptr);
+ if (iter != m_d->wrapperMapper.end()) {
+ m_d->destroying = true;
+ invalidateWrapper(iter->second);
+ m_d->destroying = false;
+ }
+}
+
+void BindingManager::destroyWrapper(SbkBaseWrapper* wrapper)
+{
+ m_d->destroying = true;
+ invalidateWrapper(wrapper);
+ m_d->destroying = false;
+}
+
+
void BindingManager::transferOwnershipToCpp(SbkBaseWrapper* wrapper)
{
if (wrapper->parentInfo)
diff --git a/libshiboken/bindingmanager.h b/libshiboken/bindingmanager.h
index d6985ccc7..2f486829f 100644
--- a/libshiboken/bindingmanager.h
+++ b/libshiboken/bindingmanager.h
@@ -64,6 +64,10 @@ public:
void addClassInheritance(SbkBaseWrapperType* parent, SbkBaseWrapperType* child);
SbkBaseWrapperType* resolveType(void* cptr, SbkBaseWrapperType* type);
+
+ /// Called by wrapper destructor
+ void destroyWrapper(const void* cptr);
+ void destroyWrapper(SbkBaseWrapper* wrapper);
private:
~BindingManager();
// disable copy