解决Boost.Python中的重载问题

1 投票
1 回答
809 浏览
提问于 2025-04-15 20:22

我有一个这样的C++类:

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

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

我的模板和重载在编译时就是一组固定的类型。应用程序代码从ConnectionBase派生,并重写它关心的事件的OnEvent函数。我之所以能这样做,是因为这些类型是已知的。OnEvent是私有的,因为用户不会直接调用它,这个类会创建一个线程来作为回调调用它。这个C++代码是可以工作的。

我把它封装在boost.python里,可以从Python中导入并发布。我想在Python中创建以下等效的内容:

class ConnectionDerived
{
public:
    ConnectionDerived();

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

我不想暴露默认的OnEvent函数,因为它们从应用程序代码中永远不会被调用——我只想提供一个供C++类调用的实现。但是……因为Python没有类型,而且我看到的所有处理内部的boost.python示例都是在C++那边的,所以我有点困惑,不知道该怎么做。我该如何重写特定的重载呢?

1 个回答

2

在C++中创建可以在Python中被重写的虚函数需要一些工作,具体可以参考这里。你需要在一个派生类中创建一个包装函数,这个函数会调用Python的方法。下面是它的工作方式:

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.
    ;
}

一些注意事项:

  • 因为你不会从Python中调用基类的OnEvent函数,所以你不需要用.def来定义它。如果你想定义它,你需要给这两个重载版本起不同的名字,像这里所示。

  • 这两个重载会调用不同的Python方法:OnEventOverloadAOnEventOverloadB。另一种选择是让它们都调用同一个方法OnEvent,这样一个Python方法就可以重写这两个重载。

撰写回答