Add peekref_method support, to solve an issue related to virtual methods, user classes, and reference counting.
This commit is contained in:
1 parent
76c1e4e888
commit
aae1dcfe7e
6 files changed
+102
-12
No files matched your search
@@ -174,3 +174,27 @@ template <> std::string TypeNameGet<int> (void)
|
||||
{
|
||||
return "int";
|
||||
}
|
||||
|
||||
|
||||
static Zbr *g_zbr = NULL;
|
||||
int Zbr::instance_count = 0;
|
||||
|
||||
void store_zbr (Zbr *zbr)
|
||||
{
|
||||
if (g_zbr)
|
||||
g_zbr->Unref ();
|
||||
g_zbr = zbr;
|
||||
}
|
||||
|
||||
int invoke_zbr (int x)
|
||||
{
|
||||
return g_zbr->get_int (x);
|
||||
}
|
||||
|
||||
void delete_stored_zbr (void)
|
||||
{
|
||||
if (g_zbr)
|
||||
g_zbr->Unref ();
|
||||
g_zbr = NULL;
|
||||
}
|
||||
|
||||
+20
-4
@@ -91,21 +91,21 @@ public:
|
||||
Foo* get_hidden_subclass_pointer ();
|
||||
|
||||
class Zbr
|
||||
// -#- incref_method=Ref; decref_method=Unref -#-
|
||||
// -#- incref_method=Ref; decref_method=Unref; peekref_method=GetReferenceCount -#-
|
||||
{
|
||||
int m_refcount;
|
||||
std::string m_datum;
|
||||
public:
|
||||
Zbr () : m_refcount (1), m_datum ("")
|
||||
{}
|
||||
{ Zbr::instance_count++; }
|
||||
Zbr (std::string datum) : m_refcount (1), m_datum (datum)
|
||||
{}
|
||||
{ Zbr::instance_count++; }
|
||||
|
||||
std::string get_datum () const { return m_datum; }
|
||||
|
||||
Zbr (Zbr const & other) :
|
||||
m_refcount (1), m_datum (other.get_datum ())
|
||||
{}
|
||||
{Zbr::instance_count++;}
|
||||
|
||||
void Ref () {
|
||||
// std::cerr << "Ref Zbr " << this << " from " << m_refcount << std::endl;
|
||||
@@ -116,8 +116,24 @@ public:
|
||||
if (--m_refcount == 0)
|
||||
delete this;
|
||||
}
|
||||
int GetReferenceCount () const { return m_refcount; }
|
||||
|
||||
virtual int get_int (int x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
static int instance_count;
|
||||
|
||||
virtual ~Zbr () {
|
||||
--Zbr::instance_count;
|
||||
}
|
||||
};
|
||||
|
||||
// -#- @zbr(transfer_ownership=true) -#-
|
||||
void store_zbr (Zbr *zbr);
|
||||
int invoke_zbr (int x);
|
||||
void delete_stored_zbr (void);
|
||||
|
||||
|
||||
class Foobar
|
||||
{
|
||||
|
||||
@@ -90,13 +90,22 @@ def my_module_gen(out_file):
|
||||
|
||||
|
||||
## Zbr is a reference counted class
|
||||
Zbr = CppClass('Zbr', incref_method='Ref', decref_method='Unref')
|
||||
Zbr = CppClass('Zbr', incref_method='Ref', decref_method='Unref',
|
||||
peekref_method="GetReferenceCount", allow_subclassing=True)
|
||||
mod.add_class(Zbr)
|
||||
Zbr.add_constructor(
|
||||
CppConstructor([Parameter.new('std::string', 'datum')]))
|
||||
Zbr.add_method(CppMethod(ReturnValue.new('std::string'), 'get_datum', []))
|
||||
Zbr.add_method(CppMethod(ReturnValue.new('int'), 'get_int', [Parameter.new('int', 'x')],
|
||||
is_virtual=True))
|
||||
Zbr.add_static_attribute(ReturnValue.new('int'), 'instance_count')
|
||||
|
||||
|
||||
mod.add_function(Function(ReturnValue.new('void'), 'store_zbr',
|
||||
[Parameter.new('Zbr*', 'zbr', transfer_ownership=True)]))
|
||||
mod.add_function(Function(ReturnValue.new('int'), 'invoke_zbr',
|
||||
[Parameter.new('int', 'x')]))
|
||||
mod.add_function(Function(ReturnValue.new('void'), 'delete_stored_zbr', []))
|
||||
|
||||
|
||||
mod.add_function(Function(ReturnValue.new('int'), 'print_something',
|
||||
[Parameter.new('const char*', 'message')]))
|
||||
|
||||
+33
-3
@@ -252,9 +252,7 @@ class TestFoo(unittest.TestCase):
|
||||
while gc.collect():
|
||||
pass
|
||||
count_before = foo.SomeObject.instance_count
|
||||
obj = Test("xxx", "yyy")
|
||||
foo.store_some_object(obj)
|
||||
del obj
|
||||
foo.store_some_object(Test("xxx", "yyy"))
|
||||
while gc.collect():
|
||||
pass
|
||||
|
||||
@@ -612,5 +610,37 @@ class TestFoo(unittest.TestCase):
|
||||
x = c.invoke_protected_virtual(2)
|
||||
self.assertEqual(x, 9)
|
||||
|
||||
|
||||
def test_subclass_with_reference_counting(self):
|
||||
class Test(foo.Zbr):
|
||||
def __init__(self, y):
|
||||
super(Test, self).__init__("foo")
|
||||
self.y = y
|
||||
def _get_int(self, x):
|
||||
return getattr(self, 'y', 0) + x
|
||||
|
||||
while gc.collect():
|
||||
pass
|
||||
count_before = foo.Zbr.instance_count
|
||||
foo.store_zbr(Test(123))
|
||||
while gc.collect():
|
||||
pass
|
||||
|
||||
## check that Zbr isn't prematurely deleted
|
||||
self.assertEqual(foo.Zbr.instance_count, count_before + 1)
|
||||
|
||||
## invoke the virtual method and check that it returns the correct value
|
||||
value = foo.invoke_zbr(456)
|
||||
self.assertEqual(value, 123+456)
|
||||
|
||||
## now delete the object from the C side..
|
||||
foo.delete_stored_zbr()
|
||||
while gc.collect():
|
||||
pass
|
||||
|
||||
## check that Zbr was finally deleted
|
||||
self.assertEqual(foo.Zbr.instance_count, count_before)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user