[C++-sig] call policies help needed

David Abrahams dave at boost-consulting.com
Wed May 24 13:52:29 CEST 2006


"Roman Yakovenko" <roman.yakovenko at gmail.com> writes:

> Hi. Please consider next case:
>
> class A{ ... };
>
> struct B{
>     B( A& a )
>     : a( a )
>     {}
>
>     A& a;
> };
>
> In order to export class B, I have to create access function for
> member variable a.
>
> A& get_a( B& b ){ return b.a };
>
> BOOST_PYTHON_MODULE(module){
>     class_< A > ...;
>     class_< B >( "B", bp::init< A& >( )[with_custodian_and_ward<1,2>()] )
>         .add_property( "a", make_funtion( &get_a, ???????? ) );
> }
>
> I don't know what call policies pyplusplus, code generator,  should
> give for make_function
> by default. Why? Because there are different use case:
>
> 1. Python code:
>     a = module.A()
>     b = module.B( a )
>     In this case life time of "a" is already managed by boost.python,
> so the return value
>     policy for make_function could be "return_existing_object". I
> think, that in this case
>     it is safe to use it.( Am I wrong ? )

It's safe until someone does 

     >>> del a

then b is dangling.

> 2. Python code:
>     a = module.get_the_a_object() # returns reference to existing
> object a, that was created
>                                                  # from C++, life time
> of this object is not managed
>                                                  # by boost.python
>     b = module.B( a )
>     In this case it is unsafe to use "return_existing_object". 

It's exactly as safe as in the previous case.

> The safer alternatives are:
>
>     1. to use "copy_[non]_const_reference", 

That's safe from crashes.

>         will not work for all classes, also
>         this is not an expected behaviour:
>         b.a.s = 2
>         will not take effect, because b.a will return copy of a

Yes, that's the tradeoff.

>     2. to use "return_internal_reference". Here I make small
> assumption, that developer
>         has some guaranties: object "a" will not be destroyed, if
> there is at least one "b"
>         object.

No, it guarantees that the B Python object will not be destroyed as
long as there is at least one A Python object that has been
retrieved via

    >>> b.a

>         Obviously this guarantee exists in C++ code, but C++ code
>         does not have garbage collector. In Python, object "b",
>         could leave longer then object "a".  So I am not sure about
>         this option too.
>
>     3. "return_existing_object"
>
>     4. I am sure, I missed something.

In principle the C++ code has unsafety built into it, since a B object
can always outlive an A object.  There's no safe choice with expected
behavior that you can derive merely by looking at C++ declarations;
you need to analyze the semantics of the C++ code, which might lead
you to discover that there's no way to get both safety and expected
behavior for this interface.  

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com




More information about the Cplusplus-sig mailing list