summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcelo Lira <marcelo.lira@openbossa.org>2009-11-29 01:26:56 -0300
committerMarcelo Lira <marcelo.lira@openbossa.org>2009-11-30 13:50:08 -0300
commit78bf7bca1fe92052ae7b64827ae81bbe25bd8c3d (patch)
tree19bd083348c0ad3aaa9c479a2fcb239004be26b0
parent697f24dfa96b15a46e9e5afa79e102e9a5100d73 (diff)
downloadshiboken-78bf7bca1fe92052ae7b64827ae81bbe25bd8c3d.tar.gz
shiboken-78bf7bca1fe92052ae7b64827ae81bbe25bd8c3d.tar.xz
shiboken-78bf7bca1fe92052ae7b64827ae81bbe25bd8c3d.zip
Added method to take care of the details of ownership transfer to C++.
Simple ownership transference, i.e. without parenting, is now performed by the new BindingManager::transferOwnershipToCpp method. It remove the parent of the transfered object and proceeds transfer or invalidation if needed. The generated code for simple ownership transfer from Python to C++ now reflects this change. Fixed the method BlackBox::keepObjectType that steals an ObjectType ownership to C++ to remove it from its parent also. The BlackBox class does not take care of the stolen object as a proper parent would, but its destructor deletes the object, so the "unparenting" is needed to avoid freeing the same memory twice. Created an unit test that adds children to a parent ObjectType and then steal the children to C++ with BlackBox.keepObjectType. Reviewed by Hugo Lima <hugo.lima@openbossa.org>
-rw-r--r--cppgenerator.cpp23
-rw-r--r--libshiboken/bindingmanager.cpp11
-rw-r--r--libshiboken/bindingmanager.h8
-rw-r--r--tests/libsample/blackbox.cpp1
-rwxr-xr-xtests/samplebinding/ownership_invalidate_child_test.py64
5 files changed, 91 insertions, 16 deletions
diff --git a/cppgenerator.cpp b/cppgenerator.cpp
index 625d48b7..5847b556 100644
--- a/cppgenerator.cpp
+++ b/cppgenerator.cpp
@@ -1183,22 +1183,13 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f
}
s << INDENT;
- if (arg_mod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::TargetLangOwnership) {
- s << "PyBaseWrapper_setOwnership(" << pyArgName << ", true);" << endl;
- } else if (wrappedClass->hasVirtualDestructor()) {
- s << "if (PyBaseWrapper_containsCppWrapper(" << pyArgName << "))" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "PyBaseWrapper_setOwnership(" << pyArgName << ", false);" << endl;
- }
- s << INDENT << "else" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "BindingManager::instance().invalidateWrapper(" << pyArgName << ");" << endl;
- }
- } else {
- s << "BindingManager::instance().invalidateWrapper(" << pyArgName << ");" << endl;
- }
+ if (arg_mod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::TargetLangOwnership)
+ s << "PyBaseWrapper_setOwnership(" << pyArgName << ", true";
+ else if (wrappedClass->hasVirtualDestructor())
+ s << "BindingManager::instance().transferOwnershipToCpp(" << pyArgName;
+ else
+ s << "BindingManager::instance().invalidateWrapper(" << pyArgName;
+ s << ");" << endl;
}
}
}
diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp
index 3610e290..8c8be3e4 100644
--- a/libshiboken/bindingmanager.cpp
+++ b/libshiboken/bindingmanager.cpp
@@ -153,5 +153,16 @@ void BindingManager::invalidateWrapper(const void* cptr)
invalidateWrapper(iter->second);
}
+void BindingManager::transferOwnershipToCpp(PyBaseWrapper* wrapper)
+{
+ if (wrapper->parentInfo)
+ Shiboken::removeParent(wrapper);
+
+ if (PyBaseWrapper_containsCppWrapper(wrapper))
+ PyBaseWrapper_setOwnership(wrapper, false);
+ else
+ invalidateWrapper(wrapper);
+}
+
} // namespace Shiboken
diff --git a/libshiboken/bindingmanager.h b/libshiboken/bindingmanager.h
index fe5767d3..602066f9 100644
--- a/libshiboken/bindingmanager.h
+++ b/libshiboken/bindingmanager.h
@@ -64,6 +64,14 @@ public:
/// 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(PyBaseWrapper* wrapper);
+ /// Convenience method to call transferOwnershipToCpp with a properly cast PyBaseWrapper.
+ inline void transferOwnershipToCpp(PyObject* wrapper)
+ {
+ transferOwnershipToCpp(reinterpret_cast<PyBaseWrapper*>(wrapper));
+ }
+
private:
~BindingManager();
// disable copy
diff --git a/tests/libsample/blackbox.cpp b/tests/libsample/blackbox.cpp
index f917d786..563b562d 100644
--- a/tests/libsample/blackbox.cpp
+++ b/tests/libsample/blackbox.cpp
@@ -55,6 +55,7 @@ BlackBox::keepObjectType(ObjectType* object)
m_ticket++;
std::pair<int, ObjectType*> item(m_ticket, object);
m_objects.insert(item);
+ object->setParent(0);
return m_ticket;
}
diff --git a/tests/samplebinding/ownership_invalidate_child_test.py b/tests/samplebinding/ownership_invalidate_child_test.py
new file mode 100755
index 00000000..763c5a89
--- /dev/null
+++ b/tests/samplebinding/ownership_invalidate_child_test.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# 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.
+# #
+# 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
+
+'''Tests for invalidating a C++ created child that was already on the care of a parent.'''
+
+import unittest
+
+from sample import ObjectType, BlackBox
+
+
+class InvalidateChildTest(unittest.TestCase):
+ '''Tests for invalidating a C++ created child that was already on the care of a parent.'''
+
+ def testInvalidateChild(self):
+ '''Invalidating method call should remove child from the care of a parent if it has one.'''
+ parent = ObjectType()
+ child1 = ObjectType(parent)
+ child1.setObjectName('child1')
+ child2 = ObjectType.create()
+ child2.setParent(parent)
+ child2.setObjectName('child2')
+
+ self.assertEqual(parent.children(), [child1, child2])
+
+ bbox = BlackBox()
+
+ # This method steals ownership from Python to C++.
+ bbox.keepObjectType(child1)
+ self.assertEqual(parent.children(), [child2])
+
+ bbox.keepObjectType(child2)
+ self.assertEqual(parent.children(), [])
+
+ del parent
+
+ self.assertEqual(child1.objectName(), 'child1')
+ self.assertRaises(RuntimeError, child2.objectName)
+
+if __name__ == '__main__':
+ unittest.main()
+