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

David Abrahams dave at boost-consulting.com
Wed Dec 24 14:23:54 CET 2003


Marc Kwiatkowski <Marc.Kwiatkowski at veritas.com> writes:

> Yet another question/observation about register_ptr_to_python.
>
> Given a function that returns a ref-ptr, it seems that all that is
> really necessary is to provide a get_pointer template function for it
> and then invoke the register_to_python function.  

That's right.

> None of the wrapper stuff is necessary.  

What "wrapper stuff"?  Do you mean A_wrapper in the example in the
docs?

> For example:
>
>     class X {
>     public:
>         X(wstring const& aValue) : value(aValue) {}
>         wstring value;
>     };
>
>     my_ref_ptr<X> NewX(wstring const& aValue )
>         { return my_ref_ptr<X>(new X(aValue)); }
> 	      
>     namespace boost { namespace python {
>
>     template <class T> T* get_pointer(my_ref_ptr<T> const& p) {
>         return p.get();
>     }
>     }}
>     
>     BOOST_PYTHON_MODULE(test) {
>
>         class_<X>("X", init<wstring const&>())
>             .def_readwrite("value", &X::value);
>
>         def("NewX", &NewX);
>
>         register_ptr_to_python< my_ref_ptr< X > >();
>    }
>
> That's all there is too it.  This seems so much more straight forward
> than the sample described in
> libs/python/doc/v2/register_ptr_to_python.html

It illustrates something different from your code.

> On the other hand, when I used ref-ptrs with a mix of derived and base
> classes, I can find no permutation of wrapper and smart pointer that
> will work to get at a base method from a derived object ptr that is
> downcast to a base object pointer.

That's an upcast.

> For example, given the Base, Derived, and Factory classes attached
> below, the following script fails
>
>>>> from pytest import Base, Factory, Derived;f=Factory()
>>>> d=f.NewDerived("i am derived")
>>>> d.GetString()
> u'i am derived'
>>>> b=f.Downcast(d)
>>>> b.GetString()
> Traceback (most recent call last):
>   File "<stdin>", line 1, in ?
> Boost.Python.ArgumentError: Python argument types in
>     Derived.GetString(Derived)
> did not match C++ signature:
>     GetString(class Filer::Test::Example::PyDerivedWrapper {lvalue})
>     GetString(class Filer::Test::Example::PyDerived {lvalue})

Well, you didn't include enough information to make this problem
reproducible (a definition of my_ref_ptr is missing, and I don't know
what else), so there's only so much I can do to help.

>From this part of the error message

   Derived.GetString(Derived)

it's clear that b is actually a Python Derived object, not a Base
object as one would expect (try doing print type(b)).  It seems like
there's something very wrong here, and the only explanation I can
come up with is that my_ref_ptr<Base>::element_type is Derived.  See
http://www.boost-consulting.com/boost/libs/python/doc/v2/pointee.html.

The other thing that looks suspicious is that you haven't declared an
inheritance relationship between Base and Derived using bases<...>.
There'd be no need to expose GetString again in Derived if you did
that.

HTH,

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





More information about the Cplusplus-sig mailing list