[C++-sig] pybindgen: allow_subclassing option causing reference parameters to be copied?

Gustavo Carneiro gjcarneiro at gmail.com
Sun Jun 28 17:19:31 CEST 2009


2009/6/25 Gustavo Carneiro <gjcarneiro at gmail.com>

>
>
> 2009/6/25 J. Michael Owen <mikeowen at llnl.gov>
>
>> I can see what you're worried about here, but as a practical matter it is
>> very useful to be able to pass stuff by reference, and copying it under the
>> hood will break code.  For instance, if the virtual functions modify the
>> state of the parameters passed by reference it will just not function
>> correctly when a copy is made.  Or in the example I sent when copy
>> constructors are not available it won't even compile!
>>
>> In Boost.Python this can be handled by wrapping the intermediate arguments
>> with the boost::ref() function, which tells Boost.Python to pass the thing
>> along as reference rather than making a copy and on my own head be it if I
>> do something nefarious with that reference.  I guess what I would like in
>> this case is the equivalent of an "on my own head be it" option.  This is
>> kind of how I think of the pointer passing policy, like with the
>> "caller_owns_return" option.  Wouldn't it be reasonable to allow us to
>> specify optionally that references should not be copied, but rather passed
>> along natively?  With the default policy still being the more memory safe
>> option of doing the copy?
>
>
> I can't really fault your logic.
>
> I just thought of something that makes some sense.  If the wrapper did
> something like:
>
> _wrap_my_virtual_method (A &a)
> {
>    PyA *py_A;
>
>    py_A = PyObject_New(PyA, &PyA_Type);
>    py_A->obj = &a;
>
>    // --- code to call into Python (without consuming a reference to py_A)
> ---
>
>    py_A->obj = NULL;
>    Py_DECREF(py_A);
> }
>
> At the end of the virtual method call, if the called python code decided to
> keep a reference to py_A, it will have a py_A with NULL C++ object and so
> any method call on it will crash.
>

After starting to look at this issue, I realized that this solution is
already implemented actually, but I had forgotten! :P

You need to tell pybindgen that the reference parameter is INOUT, thus:

    ReferenceManipulator.add_method('do_manipulate_object', 'void',
                                    [Parameter.new('ManipulatedObject&',
'obj', direction=Parameter.DIRECTION_INOUT)],
                                    is_virtual=True, is_pure_virtual=True)

Then everything works as expected.  I am closing the bug by merely adding a
unit test to cover this problem.  Should work in pybindgen 0.10 as well.

Take care,

-- 
Gustavo J. A. M. Carneiro
INESC Porto, Telecommunications and Multimedia Unit
"The universe is always one step beyond logic." -- Frank Herbert
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20090628/8afdc629/attachment.htm>


More information about the Cplusplus-sig mailing list