[C++-sig] shared_ptr and register_ptr_to_python

Jim Bosch talljimbo at gmail.com
Mon Oct 11 00:42:59 CEST 2010


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<void>(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_<C,bases<B>,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<manage_new_object>, 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


More information about the Cplusplus-sig mailing list