[C++-sig] Python-overridable method taking const ref?

Paul Melis pyplusplus at assumetheposition.nl
Wed Feb 4 19:49:18 CET 2009


Hello,

Classes with protected destructors (as found when custom reference
counting is used) seem to cause some trouble when using bp::wrapper<>
containing  a method that takes a const reference to a refcounted class.

Say I have:

#include <cstdio>
#include <boost/python.hpp>

namespace bp = boost::python;

class Thing
{
protected:
    virtual ~Thing() {}
};

class Callback
{
public:
    Callback() { }
    virtual void execute(const Thing& t) { }
protected:
    virtual ~Callback() {}
};

And I want to add a wrapper class so that Callback can be derived from
in Python and its execute() method overridden.
Simply writing

struct CallbackWrap : Callback, bp::wrapper<Callback>
{
    void execute(const Thing& t)
    {
        if (bp::override ovr = this->get_override("execute"))
        {
            fprintf(stderr, "have override, calling...\n");
            ovr(t);
            fprintf(stderr, "done calling\n");
        }
        else
            Callback::execute(t);
    }

    void default_execute(const Thing& t)
    {
        fprintf(stderr, "default\n");
        this->Callback::execute(t);
    }
};

BOOST_PYTHON_MODULE(doh)
{
    bp::class_<Thing, boost::noncopyable>("Thing")
    ;

    bp::class_<CallbackWrap, boost::noncopyable>("Callback")
        .def("execute", &Callback::execute, &CallbackWrap::default_execute)
    ;
}

doesn't cut it as I get a compile error due to Thing::~Thing() being
protected.
I've found in the archive the trick you can use to wrap a normal method
taking a const reference, e.g.

void
Callback_execute(Callback& self, Thing& t)
{
    // Work around the const Thing& parameter
    self.execute(t);
}

bp::class_<Callback>("Callback")
    .dep("execute", &Callback_execute)
;

But I don't see how I can use that in the case of the wrapper class. I
tried adding functions that do the equivalent thing but for method
Callback::execute() and CallbackWrap::default_execute() but that doesn't
compile. And I can't find in the documentation of class_<>::def() the
exact requirements for the special case of .def() that is used when the
extra default implementation is specified.

Is there a way to get wrapper classes to work in this situation?

Thanks,
Paul



More information about the Cplusplus-sig mailing list