[C++-sig] Re: register_ptr_to_python docs and test

David Abrahams dave at boost-consulting.com
Wed Jun 25 03:12:01 CEST 2003


Nicodemus <nicodemus at globalite.com.br> writes:

> <h2>Introduction</h2>
>
>   <code><boost/python/converter/register_ptr_to_python.hpp></code>
          ^                                                 ^
          &lt;                                              &gt;

You have this problem throughout.  Did you validate your html?

>   defines a function that allows the user to register smart pointers for
>   classes with virtual member functions that will be overwritten in
>   Python.

You mean "overridden" and not "overwritten".  But this has nothing at
all to do with virtual member functions AFAICT.

  <code>&lt;boost/python/converter/register_ptr_to_python.hpp&gt;</code>
  supplies <code>register_ptr_to_python</code>, a function template
  which registers a conversion from a smart pointers to Python.  The
  resulting Python object holds a copy of the converted smart pointer,
  but behaves as though it were a wrapped copy of the pointee.  If
  the pointee type has virtual functions and the class representing
  its dynamic (most-derived) type has been wrapped, the Python object
  will be an instance of the wrapper for the most-derived type.

>   Classes that have virtual methods (and the user has supplied a
>   wrapper, <code>X_Wrapper</code>, allowing Python to callback into
>   C++) live in Python not as <code>X</code> objects, but as
>   instances of the wrapper class.  This is a problem because
>   conversions to-python of <code>smart_ptr<X></code> objects won't
>   work since the objects that live in Python are held actually by
>   <code>smart_ptr<X_Wrapper></code> instances.

OK, this is one reason you might want to do use
register_ptr_to_python, but it's not the only reason.

>   Using the function in this header to register the smart pointer allows
>   correct conversion to-python of <code>smart_ptr<X></code> instances,
>   but has one drawback: a <code>X</code> object created in Python will not be
>   able to be passed as a <code>smart_ptr<X>&amp;</code> argument. 
>   But it is still possible to pass a X object created in Python as
>   <code>smart_ptr<X></code>, <code>smart_ptr<X_Wrapper></code>,
>   <code>smart_ptr<X> const&amp;</code>, or
>   <code>smart_ptr<X_Wrapper> const&amp;</code> as an argument.

That's because, unless X is wrapped with smart_ptr<X> as a template
argument to its class_<...>, X objects created in Python are held
directly in the containing Python object.

>   
> <h2>Functions</h2>
>
> Example(s)</h2>
>
> <h3>C++ Wrapper Code</h3>
>
> Here is an example of a module that contains a class <code>A</code> with
> virtual methods and some functions that work with
          ^^^^^^^
functions.

> <code>boost::shared_ptr<A></code>.
>
>
> struct A
> {
>     virtual int f() { return 0; }
> };
>
> shared_ptr<A> New() { return shared_ptr<A>( new A() ); }
>
> int Ok( const shared_ptr<A>&amp; a ) { return a->f(); }
>
> int Fail( shared_ptr<A>&amp; a ) { return a->f(); }
>
> struct A_Wrapper: A
> {
>     A_Wrapper(PyObject* self_): self(self_) {}
>     int f() { return call_method<int>(self, "f"); }    
>     int default_f() { return A::f(); }    
>     PyObject* self;
> };
>
> BOOST_PYTHON_MODULE(register_ptr)
> {
>     class_<A, A_Wrapper>("A")
>         .def("f", &amp;A::f, &amp;A_Wrapper::default_f)
>     ;
>     
>     def("New", &amp;New);
>     def("Ok", &amp;Call);
>     def("Fail", &amp;Fail);
>     
>     register_ptr_to_python< shared_ptr<A> >();
> } 
>
>
> <h3>Python Code</h3>
>
>
>>>> from register_ptr import *
>>>> a = A()
>>>> Ok(a)     # ok, passed as shared_ptr<A>
> 0
>>>> Fail(a)   # passed as shared_ptr<A>&amp;, and was created in Python!
> Traceback (most recent call last):
>   File "<stdin>", line 1, in ?
> TypeError: bad argument type for built-in operation
>>>>
>>>> na = New()   # now "na" is actually a shared_ptr<A> 
>>>> Ok(a)
> 0
>>>> Fail(a)
> 0
>>>>
>     
>
> If <code>shared_ptr<A></code> is registered as follows:
>
>
>     class_<A, A_Wrapper, shared_ptr<A> >("A")
>         .def("f", &amp;A::f, &amp;A_Wrapper::default_f)
>     ;            
>     
>
> There will be an error when trying to convert <code>shared_ptr<A></code> to
> <code>shared_ptr<A_Wrapper></code>:
>
>
>>>> a = New()
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> TypeError: No to_python (by-value) converter found for C++ type: class boost::shared_ptr<struct A>
>>>>    
>
>
> Revised 
>   <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
>   24 Jun, 2003
>   <!--webbot bot="Timestamp" endspan i-checksum="39359" -->
>
> &copy; Copyright ../../../../people/dave_abrahams.htm 
>   2002. All Rights Reserved.

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com





More information about the Cplusplus-sig mailing list