[C++-sig] Fwd: Re: shared_ptr and register_ptr_to_python

2010-10-10 Thread Marek Denis

On 10.10.2010 03:47, Jim Bosch wrote:


Pretty much everything you need should automatically work, whether you
use shared_ptr or raw pointers with call policies. If you've invoked
register_ptr_to_python on all the classes you're using,


That's what I couldn't get while reading Boost tutorial (the example
code didn't work either :( ).
Let's say I have three classes:

class A {};
class B : public A {};
class C : public B {};

should I later just put:
register_ptr_to_python< A >();
register_ptr_to_python< B >();
register_ptr_to_python< C >();
?

you'll find that
in Python you'll always get the most-derived class, even if it's
returned as a base class pointer or smart pointer on the C++ side.


Here is the small code snippet:

+v
boost::python::call_method(callback,"addToQueue",c);
-v

where callback is a PyObject* pointer,and 'c' is a pointer to the object.
Whenever I call this instruction, I can see that the 'c' object is being
copied (I just put some cout << "debug" << endl in the definition of the
Copy Constructor), so I assumed that Python code doesn't operate on the
object that was created in C++ module. Instead, it just operates on the
copy.


You shouldn't need any extra compiler flags. Just use Boost.Python the
way described in the tutorial, and throw in some register_ptr_to_python
invocations - that should be all you need.





--
best wishes

Marek Denis

___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig


Re: [C++-sig] shared_ptr and register_ptr_to_python

2010-10-10 Thread Jim Bosch

On 10/10/2010 03:58 AM, Marek Denis wrote:

On 10.10.2010 03:47, Jim Bosch wrote:


Pretty much everything you need should automatically work, whether you
use shared_ptr or raw pointers with call policies. If you've invoked
register_ptr_to_python on all the classes you're using,


That's what I couldn't get while reading Boost tutorial (the example
code didn't work either :( ).
Let's say I have three classes:

class A {};
class B : public A {};
class C : public B {};

should I later just put:
register_ptr_to_python< A >();
register_ptr_to_python< B >();
register_ptr_to_python< C >();
?


Actually, you want something like this:

register_ptr_to_python< boost::shared_ptr >();

If you want to use raw pointers, I don't think you need 
register_ptr_to_python (see below).



Here is the small code snippet:

+v
boost::python::call_method(callback,"addToQueue",c);
-v

where callback is a PyObject* pointer,and 'c' is a pointer to the object.
Whenever I call this instruction, I can see that the 'c' object is being
copied (I just put some cout << "debug" << endl in the definition of the
Copy Constructor), so I assumed that Python code doesn't operate on the
object that was created in C++ module. Instead, it just operates on the
copy.



I'm actually kind of surprised about this - in other circumstances 
(particularly when returning values in wrapped functions by pointer), 
Boost.Python doesn't copy pointers or references unless you explicitly 
ask it to.  One thing that may be worth trying: when you wrap C Python, 
mark it as noncopyable:


class_,boost::noncopyable>("C")

I'd be curious to see what happens with your call_method code snippet 
with that in place.


In any case, if you're willing to use shared_ptr everywhere instead of 
raw pointers, and switch your register_ptr_to_python calls as I've shown 
above, I think that will also stop any copying that's going on here. 
There should be a way to do it with raw pointers too, but I don't see it 
yet (and it may not exist).


Jim
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig


Re: [C++-sig] shared_ptr and register_ptr_to_python

2010-10-10 Thread Marek Denis

On 10.10.2010 20:15, Jim Bosch wrote:


Actually, you want something like this:

register_ptr_to_python< boost::shared_ptr >();

If you want to use raw pointers, I don't think you need
register_ptr_to_python (see below).



You are right.


I'm actually kind of surprised about this - in other circumstances
(particularly when returning values in wrapped functions by pointer),
Boost.Python doesn't copy pointers or references unless you explicitly
ask it to.


I did some tests to check it out (you can check the code at [1] )
and noticed, that when I launch the
+v
boost::python::call_method(callback,"addToQueue",c);
-v

piece of code, the object is copied after using self.queue.get() in the 
python script. This may be the magic (and/or implementation of the 
Queue.Queue) of Python layer, not Boost.Python itself.
So I believe I will have to live with the pointless (in this case) 
memory copying in my program :)



One thing that may be worth trying: when you wrap C Python,
mark it as noncopyable:

class_,boost::noncopyable>("C")

I'd be curious to see what happens with your call_method code snippet
with that in place.


I will let you know when I find somthing out.

[1] http://marek.octogan.net/python/

Using raw pointers is enough in my case, shared_ptrs would be safer, as 
different threads may delete object.


--

Marek Denis

___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig


Re: [C++-sig] shared_ptr and register_ptr_to_python

2010-10-10 Thread Jim Bosch

On 10/10/2010 02:16 PM, Marek Denis wrote:

I did some tests to check it out (you can check the code at [1] )
and noticed, that when I launch the
+v
boost::python::call_method(callback,"addToQueue",c);
-v

piece of code, the object is copied after using self.queue.get() in the
python script. This may be the magic (and/or implementation of the
Queue.Queue) of Python layer, not Boost.Python itself.
So I believe I will have to live with the pointless (in this case)
memory copying in my program :)


One thing that may be worth trying: when you wrap C Python,
mark it as noncopyable:

class_,boost::noncopyable>("C")

I'd be curious to see what happens with your call_method code snippet
with that in place.


I will let you know when I find somthing out.

[1] http://marek.octogan.net/python/

Using raw pointers is enough in my case, shared_ptrs would be safer, as
different threads may delete object.



It is indeed call_method that's generating the copy; because there's no 
place for a call policy there, it tries to use a by-value converter.  If 
you try it with boost::noncopyable, it refuses to compile for exactly 
that reason.  I'm surprised that's it's behavior (I don't think it's 
really consistent with the rest of Boost.Python, but it is what it is).


Essentially, what you need to do is pass a Python object to call_method 
(boost::python::object or PyObject *) that already contains your C++ 
object.  In order to get one, you need need to tell Boost.Python to 
construct A and B with what it calls a "back reference".  Your C++ 
constructors will be given a PyObject* by boost.python, pointing to the 
Python objects the C++ object will be wrapped in, and you can then store 
those as data members and pass the PyObject * to call_method.  You can 
find more information in the Boost.Python reference docs on class_, 
especially the "HeldType Semantics" section.


By the way, the call policies on your "gen" function should be 
return_value_policy, not return_internal_reference<>; 
the latter is for returning data members of wrapped classes and other 
things that are owned by another existing wrapped object.



Jim
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig