[C++-sig] Instance ownership transfer in constructor.

Jani Tiainen redetin at gmail.com
Fri Jul 6 12:16:06 CEST 2012


Ok, last suggestions were closest I could get: Now I see that data is 
deleted within owner destructor but still I get error messages that data 
objects are being deleted directly second time by Python.

So now I need some way to say to python that "data" classes are not 
meant to be deleted by python ever.

6.7.2012 12:57, Holger Brandsmeier kirjoitti:
> Jani,
>
> can you try what John Reid proposed but instead of
>            py::with_custodian_and_ward< 1, 2 >()
> please try to use
>            py::with_custodian_and_ward< 2, 1 >()
> or (more likely to work)
>            py::with_custodian_and_ward_postcall< 2, 1 >()
>
> This should bind the lifetime of `self` to its first argument. I just
> never tried if this is a legal thing to do in the constructor.
>
> -Holger
>
> On Fri, Jul 6, 2012 at 8:20 AM, Jani Tiainen <redetin at gmail.com> wrote:
>> Hi,
>>
>> I'm still strugling with this whole thingy so I came up with more concrete
>> example I'm trying to achieve:
>>
>> http://pastebin.com/dVRfT56x
>>
>>
>> And in python code I do like this:
>>
>> owner = Owner()
>> data = Data(owner)
>>
>> After script is finished I get warning message that Data destructor
>> shouldn't be called directly. And then python crashes due memory corruption.
>>
>> I've tried to make usage of shared_ptr but no luck and I didn't understood
>> how to apply shared_ptr_for_this.
>>
>> (NOTE: in my case all classes are from 3rd party library that I have no
>> control over)
>>
>> 5.7.2012 20:44, Holger Brandsmeier kirjoitti:
>>
>>> Jani,
>>>
>>> ok what you want to do is quite a lot more intrusive, so you need some
>>> more involved methods, but it should be possible. I would do it by
>>> noting the following
>>>    - data_1 is published to python as a boost::shared_ptr<Data> (default
>>> holder type)
>>>    - usually it is difficult for a class member function, to obtain a
>>> shared_ptr<> to itself, i.e. something like `this` but not of type
>>> Data* but of boost::shared_ptr<Data>.
>>>    - fortunately there is something supported by boost itself, called
>>> `enable_shared_from_this`, see
>>>
>>> http://stackoverflow.com/questions/142391/getting-a-boostshared-ptr-for-this
>>>    - Now you want `owner` to hold on to this `shared_ptr<Data>` which
>>> ensures that `data_1` does not get deleted before `owner`, you can do
>>> this by
>>>     owner->setData( shared_from_this() )
>>> in any member function of `Data`.
>>>    - Note that I _think_ that you are not allowed to use
>>> `shared_from_this()` in the constructor itself, so you might have to
>>> use boost::pythons `make_constructor` to make an ordinary member /
>>> non-member function behave as the constructor in python.
>>>
>>> Maybe someone has a quicker way of doing this, but remember that this
>>> is exactly the use case that `shared_ptr` are made for,
>>> Holger
>>>
>>>
>>> On Thu, Jul 5, 2012 at 6:47 PM, Jani Tiainen <redetin at gmail.com> wrote:
>>>>
>>>> I want to do it another way around:
>>>>
>>>> Instance of Owner should hold reference to data_1 and data_2 as long as
>>>> owner is alive.
>>>>
>>>> Now following happens:
>>>> owner = Owner()
>>>> data_1 = Data(owner) # data_1 ownership is transferred to owner object
>>>> data_2 = Data(owner) # data_2 ownership is transferred to owner object
>>>>
>>>> print owner.get_data_objects()
>>>>
>>>> <data_1>, <data_2>
>>>>
>>>> del data_1
>>>> del data_2
>>>>
>>>> print owner.get_data_objects()
>>>> # Crash because data_1 and data_2 are deleted even owner should still
>>>> hold
>>>> the reference.
>>>>
>>>> I tried to do it like
>>>> http://www.boost.org/doc/libs/1_49_0/libs/python/test/injected.cpp  but
>>>> it
>>>> didn't worked for me.
>>>>
>>>>
>>>> On Thu, Jul 5, 2012 at 7:00 PM, John Reid <j.reid at mail.cryst.bbk.ac.uk>
>>>> wrote:
>>>>>
>>>>>
>>>>> On 05/07/12 11:49, Jani Tiainen wrote:
>>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> I'm new to python.boost library and I'm trying to use it to wrap a
>>>>>> third
>>>>>> party library. Everything else I've managed to get working - thanks to
>>>>>> excellent library and lot of examples I've found around a net.
>>>>>>
>>>>>> Only thing I can't get working properly is instance ownership transfer
>>>>>> in constructor.
>>>>>>
>>>>>> So classes in library are defined like follows:
>>>>>>
>>>>>> class Owner {
>>>>>> ...
>>>>>> }
>>>>>>
>>>>>> class Data {
>>>>>>       Data(Owner *owner); // <-- Here happens ownership transfer.
>>>>>> }
>>>>>>
>>>>>>
>>>>>> Python code is like follows:
>>>>>>
>>>>>> owner = Owner()
>>>>>> data_1 = Data(owner)
>>>>>> data_2 = Data(owner)
>>>>>>
>>>>>> So when Python script stops runnning it causes crash due the fact that
>>>>>> I've data objects are automatically destroyed by Owner-class but Python
>>>>>> deletes them by using Data-class destructor (which shouldn't happen
>>>>>> ever).
>>>>>>
>>>>>
>>>>> If I understand you correctly then you want the owner object to remain
>>>>> alive at least as long as data_1 and data_2? If so you could use
>>>>> with_custodian_and_ward:
>>>>>
>>>>>
>>>>> http://www.boost.org/doc/libs/1_49_0/libs/python/doc/v2/with_custodian_and_ward.html
>>>>>
>>>>> For example something like the following should work:
>>>>>
>>>>>           namespace py = boost::python;
>>>>>           py::class_<
>>>>>                   ...
>>>>>           > my_class(
>>>>>               "Data",
>>>>>               "docstring.",
>>>>>               py::init< Owner * >( "Constructor." )[
>>>>>                   py::with_custodian_and_ward< 1, 2 >()
>>>>>               ]
>>>>>           );
>>>>>
>>>>> _______________________________________________
>>>>> Cplusplus-sig mailing list
>>>>> Cplusplus-sig at python.org
>>>>> http://mail.python.org/mailman/listinfo/cplusplus-sig
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> Jani Tiainen
>>>>
>>>> - Well planned is half done, and a half done has been sufficient
>>>> before...
>>>>
>>>>
>>>> _______________________________________________
>>>> Cplusplus-sig mailing list
>>>> Cplusplus-sig at python.org
>>>> http://mail.python.org/mailman/listinfo/cplusplus-sig
>>>
>>> _______________________________________________
>>> Cplusplus-sig mailing list
>>> Cplusplus-sig at python.org
>>> http://mail.python.org/mailman/listinfo/cplusplus-sig
>>>
>>
>>
>> --
>> Jani Tiainen
>>
>> - Well planned is half done and a half done has been sufficient before...
>>
>>
>>
>> _______________________________________________
>> Cplusplus-sig mailing list
>> Cplusplus-sig at python.org
>> http://mail.python.org/mailman/listinfo/cplusplus-sig
> _______________________________________________
> Cplusplus-sig mailing list
> Cplusplus-sig at python.org
> http://mail.python.org/mailman/listinfo/cplusplus-sig
>


-- 
Jani Tiainen

- Well planned is half done and a half done has been sufficient before...




More information about the Cplusplus-sig mailing list