【问题标题】:override a C++ virtual function within Python with Boost.python?用 Boost.python 覆盖 Python 中的 C++ 虚函数?
【发布时间】:2020-12-16 01:05:58
【问题描述】:

我有一个带有虚方法的 C++ 类:

//C++ A级 {

public:
    A() {};
    virtual int override_me(int a) {return 2*a;};
    int calculate(int a) { return this->override_me(a) ;}

};

我想做的是使用 Boost.python 将这个类公开给 Python,从 Python 中的这个类继承并有正确的覆盖调用:

#python:
class B(A):
   def override_me(self, a):
       return 5*a
b = B()
b.calculate(1) # should return 5 instead of 2

我想对纯虚函数做同样的事情。我正在寻找一种不在类 A 上创建 C++ 中的任何包装类的方法。这可能吗?如果是/如果不是,我该怎么做?

【问题讨论】:

  • “不在 C++ 中在 A 类上创建任何包装类” - 要求有多强? :-)
  • 无强要求。如果它是可以实现的,那么它对我有好处
  • 有一种标准的方法可以用 boost::python 将 C++ 类暴露给 Python,你试过了吗? (我个人推荐 pybind11 而不是 boost::python,这两个包在精神上非常相似,所以想法和技术可以继承)。
  • this 似乎是你想要的,但我无法让它工作:-D
  • 你为什么推荐 pybind11 而不是 boost @n.'pronouns'm。

标签: python c++ boost virtual boost-python


【解决方案1】:

您可以为您的类提供一个瘦包装器,将override_me 方法调用委托给boost::python 特定的覆盖函数。

派生类calculate调用只是调用父类calculate方法,所以当它们被Python调用时,它们调用C++定义的calculate方法,但仍然允许override_me方法被Python覆盖:

#include <boost/python.hpp>
using namespace boost;
using namespace boost::python;

class A {

public:
    A() {};
    virtual int override_me(int a) {
        return 2*a;
    };
    virtual int calculate(int a) {
        return this->override_me(a);
    }
};

struct AWrap: A, public boost::python::wrapper<A> {
    AWrap() : A() {};
    int override_me(int a) override {
        if (override f = this->get_override("override_me")) {
            return this->get_override("override_me")(a);
        } else {
            return A::override_me(a);
        }
    };
    int calculate(int a) override {
        return A::calculate(a);
    }
};

BOOST_PYTHON_MODULE(my_lib)
{
      python::class_<AWrap, boost::noncopyable>("A", python::init<>())
      .def("override_me", &AWrap::override_me)
      .def("calculate", &AWrap::calculate);
}

int main() {}

g++ virtual_override.cpp -fPIC -shared -I/path/to/include/python3 -L/path/to/libpython3 -o my_lib.so -lpython3 -lboost_python3

例子:

这允许非纯情况,例如,当 override_me 未被覆盖时,调用默认函数:

import my_lib

class B(my_lib.A):
    pass
b = B()

print (b.calculate(1))

2

但 Python 可以实现虚拟覆盖:

import my_lib

class B(my_lib.A):
   def override_me(self, a):
       return 5*a
b = B()

print (b.calculate(1))

5

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-17
    • 2020-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-22
    • 2013-01-16
    • 2013-10-04
    相关资源
    最近更新 更多