More boost::shared_ptr tests/fixes, seems stable now.

This commit is contained in:
Gustavo J. A. M. Carneiro committed 2012-08-24 19:11:24 +01:00
1 parent 4f64044480
commit a17ce14a6e
6 files changed
+88 -83

No files matched your search

+28 -9
View File
@@ -82,6 +82,9 @@ class MemoryPolicy(object):
def get_delete_code(self, cpp_class):
raise NotImplementedError
def get_pystruct_init_code(self, cpp_class, obj):
return ''
class ReferenceCountingPolicy(MemoryPolicy):
@@ -191,7 +194,7 @@ class BoostSharedPtr(SmartPointerPolicy):
self.pointer_name = '::boost::shared_ptr< %s >' % (self.class_name,)
def get_delete_code(self, cpp_class):
return "self->obj.reset ();"
return "self->obj.~shared_ptr< %s >();" % (self.class_name,)
def get_pointer_type(self, class_full_name):
return self.pointer_name + ' '
@@ -199,6 +202,9 @@ class BoostSharedPtr(SmartPointerPolicy):
def get_instance_creation_function(self):
return boost_shared_ptr_instance_creation_function
def get_pystruct_init_code(self, cpp_class, obj):
return "new(&%s->obj) %s;" % (obj, self.pointer_name,)
def default_instance_creation_function(cpp_class, code_block, lvalue,
parameters, construct_type_name):
@@ -2255,14 +2261,8 @@ static PyObject*\n%s(%s *self)
declarations = DeclarationsScope()
code_block = CodeBlock("return NULL;", declarations)
if self.allow_subclassing:
new_func = 'PyObject_GC_New'
else:
new_func = 'PyObject_New'
py_copy = declarations.declare_variable("%s*" % self.pystruct, "py_copy")
code_block.write_code("%s = %s(%s, %s);" %
(py_copy, new_func, self.pystruct, '&'+self.pytypestruct))
self.write_allocate_pystruct(code_block, py_copy)
code_block.write_code("%s->obj = new %s(*self->obj);" % (py_copy, construct_name))
if self.allow_subclassing:
code_block.write_code("%s->inst_dict = NULL;" % py_copy)
@@ -2601,7 +2601,26 @@ if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &%s)) {
'PyModule_AddObject(m, (char *) \"%s\", (PyObject *) &%s);' % (
alias, self.pytypestruct))
def write_allocate_pystruct(self, code_block, lvalue, wrapper_type=None):
"""
Generates code to allocate a python wrapper structure, using
PyObject_New or PyObject_GC_New, plus some additional strcture
initialization that may be needed.
"""
if self.allow_subclassing:
new_func = 'PyObject_GC_New'
else:
new_func = 'PyObject_New'
if wrapper_type is None:
wrapper_type = '&'+self.pytypestruct
code_block.write_code("%s = %s(%s, %s);" %
(lvalue, new_func, self.pystruct, wrapper_type))
if self.allow_subclassing:
code_block.write_code(
"%s->inst_dict = NULL;" % (lvalue,))
if self.memory_policy is not None:
code_block.write_code(self.memory_policy.get_pystruct_init_code(self, lvalue))
from cppclass_typehandlers import CppClassParameter, CppClassRefParameter, \
CppClassReturnValue, CppClassRefReturnValue, CppClassPtrParameter, CppClassPtrReturnValue, CppClassParameterBase, \
+11 -71
View File
@@ -43,13 +43,7 @@ def common_shared_object_return(value, py_name, cpp_class, code_block,
wrapper_type = '&'+cpp_class.pytypestruct
## Create the Python wrapper object
if cpp_class.allow_subclassing:
new_func = 'PyObject_GC_New'
else:
new_func = 'PyObject_New'
code_block.write_code(
"%s = %s(%s, %s);" %
(py_name, new_func, cpp_class.pystruct, wrapper_type))
cpp_class.write_allocate_pystruct(code_block, py_name, wrapper_type)
if cpp_class.allow_subclassing:
code_block.write_code(
@@ -319,13 +313,7 @@ class CppClassParameter(CppClassParameterBase):
self.py_name = wrapper.declarations.declare_variable(
self.cpp_class.pystruct+'*', 'py_'+self.cpp_class.name)
if self.cpp_class.allow_subclassing:
new_func = 'PyObject_GC_New'
else:
new_func = 'PyObject_New'
wrapper.before_call.write_code(
"%s = %s(%s, %s);" %
(self.py_name, new_func, self.cpp_class.pystruct, '&'+self.cpp_class.pytypestruct))
self.cpp_class.write_allocate_pystruct(wrapper.before_call, self.py_name)
if self.cpp_class.allow_subclassing:
wrapper.before_call.write_code(
"%s->inst_dict = NULL;" % (self.py_name,))
@@ -439,14 +427,7 @@ class CppClassRefParameter(CppClassParameterBase):
self.py_name = wrapper.declarations.declare_variable(
self.cpp_class.pystruct+'*', self.name)
if self.cpp_class.allow_subclassing:
new_func = 'PyObject_GC_New'
else:
new_func = 'PyObject_New'
wrapper.before_call.write_code(
"%s = %s(%s, %s);" %
(self.py_name, new_func, self.cpp_class.pystruct,
'&'+self.cpp_class.pytypestruct))
self.cpp_class.write_allocate_pystruct(wrapper.before_call, self.py_name)
if self.cpp_class.allow_subclassing:
wrapper.after_call.write_code(
"%s->inst_dict = NULL;" % (self.py_name,))
@@ -486,13 +467,7 @@ class CppClassRefParameter(CppClassParameterBase):
self.py_name = wrapper.declarations.declare_variable(
self.cpp_class.pystruct+'*', 'py_'+self.cpp_class.name)
if self.cpp_class.allow_subclassing:
new_func = 'PyObject_GC_New'
else:
new_func = 'PyObject_New'
wrapper.before_call.write_code(
"%s = %s(%s, %s);" %
(self.py_name, new_func, self.cpp_class.pystruct, '&'+self.cpp_class.pytypestruct))
self.cpp_class.write_allocate_pystruct(wrapper.before_call, self.py_name)
if self.cpp_class.allow_subclassing:
wrapper.before_call.write_code(
"%s->inst_dict = NULL;" % (self.py_name,))
@@ -573,13 +548,7 @@ class CppClassReturnValue(CppClassReturnValueBase):
py_name = wrapper.declarations.declare_variable(
self.cpp_class.pystruct+'*', 'py_'+self.cpp_class.name)
self.py_name = py_name
if self.cpp_class.allow_subclassing:
new_func = 'PyObject_GC_New'
else:
new_func = 'PyObject_New'
wrapper.after_call.write_code(
"%s = %s(%s, %s);" %
(py_name, new_func, self.cpp_class.pystruct, '&'+self.cpp_class.pytypestruct))
self.cpp_class.write_allocate_pystruct(wrapper.after_call, self.py_name)
if self.cpp_class.allow_subclassing:
wrapper.after_call.write_code(
"%s->inst_dict = NULL;" % (py_name,))
@@ -652,16 +621,8 @@ class CppClassRefReturnValue(CppClassReturnValueBase):
type_is_pointer=False)
else:
if self.cpp_class.allow_subclassing:
new_func = 'PyObject_GC_New'
else:
new_func = 'PyObject_New'
wrapper.after_call.write_code(
"%s = %s(%s, %s);" %
(py_name, new_func, self.cpp_class.pystruct, '&'+self.cpp_class.pytypestruct))
if self.cpp_class.allow_subclassing:
wrapper.after_call.write_code(
"%s->inst_dict = NULL;" % (py_name,))
self.cpp_class.write_allocate_pystruct(wrapper.after_call, py_name)
wrapper.after_call.write_code("%s->flags = PYBINDGEN_WRAPPER_FLAG_NONE;" % (py_name,))
self.cpp_class.write_create_instance(wrapper.after_call,
@@ -852,19 +813,9 @@ class CppClassPtrParameter(CppClassParameterBase):
wrapper_type = '&'+self.cpp_class.pytypestruct
## Create the Python wrapper object
if self.cpp_class.allow_subclassing:
new_func = 'PyObject_GC_New'
else:
new_func = 'PyObject_New'
wrapper.before_call.write_code(
"%s = %s(%s, %s);" %
(py_name, new_func, self.cpp_class.pystruct, wrapper_type))
self.py_name = py_name
if self.cpp_class.allow_subclassing:
wrapper.before_call.write_code(
"%s->inst_dict = NULL;" % (py_name,))
self.cpp_class.write_allocate_pystruct(wrapper.before_call, py_name, wrapper_type)
wrapper.before_call.write_code("%s->flags = PYBINDGEN_WRAPPER_FLAG_NONE;" % py_name)
self.py_name = py_name
## Assign the C++ value to the Python wrapper
if self.transfer_ownership:
@@ -1249,9 +1200,7 @@ class CppClassSharedPtrParameter(CppClassParameterBase):
## Find out what Python wrapper to use, in case
## automatic_type_narrowing is active and we are not forced to
## make a copy of the object
if (self.cpp_class.automatic_type_narrowing
and (self.transfer_ownership or isinstance(self.cpp_class.memory_policy,
cppclass.ReferenceCountingPolicy))):
if self.cpp_class.automatic_type_narrowing:
typeid_map_name = self.cpp_class.get_type_narrowing_root().typeid_map_name
wrapper_type = wrapper.declarations.declare_variable(
@@ -1263,18 +1212,9 @@ class CppClassSharedPtrParameter(CppClassParameterBase):
wrapper_type = '&'+self.cpp_class.pytypestruct
## Create the Python wrapper object
if self.cpp_class.allow_subclassing:
new_func = 'PyObject_GC_New'
else:
new_func = 'PyObject_New'
wrapper.before_call.write_code(
"%s = %s(%s, %s);" %
(py_name, new_func, self.cpp_class.pystruct, wrapper_type))
self.cpp_class.write_allocate_pystruct(wrapper.before_call, py_name, wrapper_type)
self.py_name = py_name
if self.cpp_class.allow_subclassing:
wrapper.before_call.write_code(
"%s->inst_dict = NULL;" % (py_name,))
wrapper.before_call.write_code("%s->flags = PYBINDGEN_WRAPPER_FLAG_NONE;" % py_name)
## Assign the C++ value to the Python wrapper
+2
View File
@@ -47,6 +47,8 @@ class ClassThatTakesFoo
public:
ClassThatTakesFoo(boost::shared_ptr<Foo> foo) : m_foo(foo) {}
boost::shared_ptr<Foo> get_foo () const { return m_foo; }
virtual boost::shared_ptr<Foo> get_modified_foo (boost::shared_ptr<Foo> foo) const { return m_foo; }
};
+6 -2
View File
@@ -14,7 +14,8 @@ from pybindgen import cppclass
from pybindgen import param, retval
import pybindgen.settings
pybindgen.settings.deprecated_virtuals = False
def my_module_gen(out_file):
@@ -38,9 +39,12 @@ def my_module_gen(out_file):
[param('boost::shared_ptr<Foo>', 'foo')])
mod.add_function('function_that_returns_foo', retval('boost::shared_ptr<Foo>'), [])
cls = mod.add_class('ClassThatTakesFoo')
cls = mod.add_class('ClassThatTakesFoo', allow_subclassing=True)
cls.add_constructor([Parameter.new('boost::shared_ptr<Foo>', 'foo')])
cls.add_method('get_foo', ReturnValue.new('boost::shared_ptr<Foo>'), [])
cls.add_method('get_modified_foo', retval('boost::shared_ptr<Foo>'),
[param('boost::shared_ptr<Foo>', 'foo')],
is_virtual=True, is_const=True)
+39 -1
View File
@@ -68,7 +68,45 @@ class TestBar(unittest.TestCase):
del f1, takes
while gc.collect():
pass
self.assertEqual(bar.Foo.instance_count, count0) # the object stays alive
self.assertEqual(bar.Foo.instance_count, count0)
def test_class_takes_foo_subclassing(self):
count0 = bar.Foo.instance_count
f = bar.Foo("hello45")
self.assertEqual(bar.Foo.instance_count, count0 + 1)
self.assertEqual(f.get_datum(), "hello45")
class Takes(bar.ClassThatTakesFoo):
def get_modified_foo(self, foo):
d = foo.get_datum()
return bar.Foo(d+"xxx")
takes = Takes(f)
del f
while gc.collect():
pass
self.assertEqual(bar.Foo.instance_count, count0+1)
f1 = takes.get_foo()
self.assertEqual(f1.get_datum(), "hello45")
self.assertEqual(bar.Foo.instance_count, count0+1)
f2 = bar.Foo("helloyyy")
self.assertEqual(bar.Foo.instance_count, count0+2)
f3 = takes.get_modified_foo(f2)
self.assertEqual(bar.Foo.instance_count, count0+3)
self.assertEqual(f3.get_datum(), "helloyyyxxx")
del f1, f2, f3, takes
while gc.collect():
pass
self.assertEqual(bar.Foo.instance_count, count0)
if __name__ == '__main__':
+2
View File
@@ -402,6 +402,8 @@ class CheckContext(Context.Context):
if env['ENABLE_BOOST_SHARED_PTR']:
print "Running boost::shared_ptr unit tests..."
retvals.append(subprocess.Popen(valgrind + [python, 'tests/boost/bartest.py'] + verbosity).wait())
else:
print "Skipping boost::shared_ptr unit tests (boost headers not found)..."
if any(retvals):
Logs.error("Unit test failures")