[C++-sig] Custom smart pointer and bp::wrapper

Paul Melis pyplusplus at assumetheposition.nl
Sat Jan 17 16:11:05 CET 2009


Given two reference-counted classes Thing and Callback, and using a
custom smart pointer ref_ptr<T>, with all the needed pointee stuff added
and using ref_ptr<..> as held type I'm getting into trouble when trying
to use a boost::python::wrapper<> derived class. See the attached files
for the complete code.

Summarized, I have:

class Referenced { /* methods ref() and unref() */ }
class Thing : public Referenced { ...}
class Callback : public Referenced { ...}

template<class T> class ref_ptr { ... }

You can set a Callback instance on Thing, and the Callback's execute()
method gets called at some point in time. The Callback class is to be
implemented in Python (although it has a default empty implementation
for execute()), so I defined:

struct CallbackWrap : Callback, bp::wrapper<Callback>
{
    void execute(Thing* t)
    {
        if (bp::override ovr = this->get_override("execute"))
            ovr(t);
        else
            Callback::execute(t);
    }

    void default_execute(Thing* t) { this->Callback::execute(t); }
};

The whole shebang is packaged up in a BP module:

BOOST_PYTHON_MODULE(doh)
{
    bp::class_<Thing, ref_ptr<Thing>, boost::noncopyable>("Thing")
        .def("update", &Thing::update)
        .def("setCallback", &Thing::setCallback)
        ;

    bp::class_<CallbackWrap, ref_ptr<CallbackWrap>,
boost::noncopyable>("Callback")  // Don't add bp::no_init, as we won't
be able to derive a class from C in that case
        .def("execute", &Callback::execute, &CallbackWrap::default_execute)
        ;
}

But when trying to run

import doh

class MyCallback(doh.Callback):
    def execute(self, t):
        print t
        return 1

m = MyCallback()

t = doh.Thing()
t.setCallback(m)
t.update()

i'm getting

Traceback (most recent call last):
  File "no_to_python_converter.py", line 12, in <module>
    t.update()
TypeError: No to_python (by-value) converter found for C++ type: Thing".

And I fail to see why...

I'm also not sure if the message really means that there is an instance
of Thing that needs to be converted to its Python equivalent, or if
there is a _pointer_ to a Thing instance that needs to be converted to
Python.
If the former, then I'm surprised these instances even show up, as the
code being wrapped doesn't pass a Thing anywhere, only a Thing*. I've
also tagged Thing as noncopyable, so I wouldn't expect Thing instances
to be passed around internally by BP by value.

It kind of feels like BP knows how to convert an ref_ptr<Thing> to a
Python object, but not how to convert a Thing.
Any help is appreciated,

Regards,
Paul
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: no_to_python_converter.cpp
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20090117/fc57beec/attachment.txt>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: no_to_python_converter.py
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20090117/fc57beec/attachment-0001.txt>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: ref_ptr.h
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20090117/fc57beec/attachment-0002.txt>


More information about the Cplusplus-sig mailing list