[C++-sig] Custodian and Ward doubts

Eric Jardim ericjardim at gmail.com
Mon Sep 12 17:02:07 CEST 2005


Hi,

I have some questions about "custodian and ward" policy that are not very 
clear on the docs.

Let's suppose we have a wrapped function "object* object::create(object* 
parent)", where the parent is the custodian (holds a internal pointer to) of 
the child, and we wrapped it correctly.

So, if in Python I do:
>>> a = create(None) # no parent
>>> b = create(a) # "a" is "b" parent and custodian
>>> del b # "b" is not deleted, because "a" is guarding it
>>> del a # no more refs, "a" and "b" are deleted

But what if I have another function "void object::setParent(object* 
parent)", where the parent is changed. So, the new parent now is going to be 
the custodian of the object. 
>>> a = create(None) 
>>> b = create(a) 
>>> c = create(None) 
>>> b.setParent(c) # c is the new parent (and should be the new custodian)
???

But what happens to the old parent (if it is not None)? Is it still a 
custodian of the child? Can a child have more than one custodian? Or is it 
like a ownership (only one is the custodian)?

I am asking it because I am having some problems with internal references 
(pointers) from C++ objects to another that Python don't see. So I get many 
objects being deleted prematurely, when they are actually being referenced 
(in C++).

Other problem that I have, is that aside from some "a" object being parent 
(custodian) of "b", internally, "a" deletes "b" and all of it's children 
recursivelly. So Python's "b" waits for Python's "a" to be deleted, and "a" 
is deleted in Python and C++. But with this C++'s "b" is deleted also, and 
when Python is going to be deleted the pointer is dangled. So, In Python "a" 
must die before "b", but in C++, "b" must die before "a". Now what?

The problem is that actually, both parent and child have references to each 
other. But I cannot make circular custodian and ward, because they would 
never get deleted. 

I manage the problem by referencing objects in Python manually, but this 
approach is not very interesting. Apart from this I can have C++ native (not 
created by Boost.Python extended classes contructors), and also, if someone 
may want to extend the library they would have to do a lot of dirty work.

I was thinking that implementing my custom call policies would be an elegant 
and less error prone solution. Basically, every time a function return a 
QObject pointer to Python, I use my custom return value policy, derived from 
reference_existing_object. Internally, I can make a list of objects and 
control when they must die. But I am afraid if this is the best solution.

Does anybody have a problem like this? Which solution do you sugest?

Thanks,

[Eric Jardim]
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20050912/179b1970/attachment.htm>


More information about the Cplusplus-sig mailing list