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

2012-07-05 Thread Jani Tiainen

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).


--
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


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

2012-07-05 Thread Jani Tiainen
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()

, 

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 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

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

2012-07-05 Thread Jani Tiainen

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 (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.
  - 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` 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  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()

, 

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 
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


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

2012-07-06 Thread Jani Tiainen
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  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 (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.
   - 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` 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  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()

, 

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 
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