You can provide a thin wrapper around your class that delegates the override_me method calls to boost::python-specific override function.
Derived class calculate calls simply call the parent class calculate method, so when they are called from Python, they call the C++ defined calculate method, but still allow override_me method to be overridden from 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
Example:
This allows for non-pure cases, for example, when override_me isn't overridden, the default function is called:
import my_lib
class B(my_lib.A):
pass
b = B()
print (b.calculate(1))
2
But virtual overrides are possible from Python:
import my_lib
class B(my_lib.A):
def override_me(self, a):
return 5*a
b = B()
print (b.calculate(1))
5