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 <rede...@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 <rede...@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.r...@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@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@python.org >>> http://mail.python.org/mailman/listinfo/cplusplus-sig >> >> _______________________________________________ >> Cplusplus-sig mailing list >> Cplusplus-sig@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@python.org > http://mail.python.org/mailman/listinfo/cplusplus-sig _______________________________________________ Cplusplus-sig mailing list Cplusplus-sig@python.org http://mail.python.org/mailman/listinfo/cplusplus-sig