More boost::shared_ptr tests/fixes, seems stable now.
This commit is contained in:
1 parent
4f64044480
commit
a17ce14a6e
6 files changed
+88
-83
No files matched your search
+28
-9
@@ -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, \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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__':
|
||||
|
||||
@@ -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")
|
||||
|
||||
Reference in new issue
Block a user