views:

68

answers:

1

I have a C++ class like this:

class ConnectionBase
{
public:
    ConnectionBase();
    template <class T> Publish(const T&);

private:
    virtual void OnEvent(const Overload_a&) {}
    virtual void OnEvent(const Overload_b&) {}
};

My templates & overloads are a known fixed set of types at compile time. The application code derives from ConnectionBase and overrides OnEvent for the events it cares about. I can do this because the set of types is known. OnEvent is private because the user never calls it, the class creates a thread that calls it as a callback. The C++ code works.

I have wrapped this in boost.python, I can import it and publish from python. I want to create the equivalent of the following in python :

class ConnectionDerived
{
public:
    ConnectionDerived();

private:
    virtual void OnEvent(const Overload_b&)
    { 
        // application code
    }
};

I don't care to (do not want to) expose the default OnEvent functions, since they're never called from application code - I only want to provide a body for the C++ class to call. But ... since python isn't typed, and all the boost.python examples I've seen dealing with internals are on the C++ side, I'm a little puzzled as to how to do this. How do I override specific overloads?

+1  A: 

Creating C++ virtual functions that can be overridden in Python requires some work - see here. You will need to create a wrapper function in a derived class that calls the Python method. Here is how it can work:

struct ConnectionBaseWrap : ConnectionBase, wrapper<ConnectionBase>
{
    void OnEvent(const Overload_a &obj) {
        if (override f = get_override("OnEventOverloadA"))
            f(obj);
    }
    void OnEvent(const Overload_b &obj) {
        if (override f = get_override("OnEventOverloadB"))
            f(obj);
    }
};

BOOST_PYTHON_MODULE(yourmodule) {
    class_<ConnectionBaseWrap, boost::noncopyable>("ConnectionBase")
        //Your additional definitions here.
    ;
}

Some notes:

  • Since you won't be calling the base class's OnEvent function from Python, you don't need to define it with .def. If you did want to define it, you'd need to give the two overloaded versions different names, like here.

  • The two overloads will call different Python methods: OnEventOverloadA and OnEventOverloadB. Another option is to have them both call the same method OnEvent, and then one Python method will override both overloads.

interjay