In this article were going to get into a bit more detail of describing the bindings of classes. Specifically were going to deal with abstract classes and polymorphism.
Consider the following:
struct AbstractClass {
virtual std::string speak() const = 0;
};
struct DerivedClassA : AbstractClass {
virtual std::string speak() const {return "Derived Class A";}
};
struct DerivedClassB : AbstractClass {
virtual std::string speak() const {return "Derived Class B";}
};
We have an Abstract Class and two derived class that implement the speak method. How do we model this in Boost Python such that in Python we can get a pointer to one of these objects and call speak on the proper derived class.
To do this we have to build a wrapper class:
struct WrapperClass : AbstractClass , boost::python::wrapper<AbstractClass> {
virtual std::string speak() const {
return this->get_override("speak")();
}
};
This wrapper class extends the AbstractClass, and extends a special boost::python::wrapper
Lastly you need to define the bindings for Python, this is similar to the Hello World example in article one:
BOOST_PYTHON_MODULE(PyHelloWorld)
{
using namespace boost::python;
def("getDerivedClassA",&getDerivedClassA,return_value_policy< manage_new_object >());
def("getDerivedClassB",&getDerivedClassB,return_value_policy< manage_new_object >());
class_<WrapperClass, boost::noncopyable > ("DerivedClass")
.def("speak",boost::python::pure_virtual(&AbstractClass::speak))
;
}
Here we added two test methods called getDerivedClassA and getDerivedClassB these will be in the package PyHelloWorld as dictated by 'BOOST_PYTHON_MODULE(PyHelloWorld)'
Lastly we want to be able to execute python in the same process as our executable. If you followed the instructions in part 1 then you simply need to add this method:
void start( ) {
using namespace boost::python;
Py_Initialize();
// Explicitly call the method that the BOOST_PYTHON_MODULE macro created.
// This sets up our DLL to be used by python.
initPyHelloWorld();
std::string pythonCommand;
try {
PyRun_SimpleString("import PyHelloWorld");
while(1) {
std::cout << ">>> ";
getline(std::cin,pythonCommand);
if (pythonCommand == "quit") {
break;
}else {
std::cout << PyRun_SimpleString(pythonCommand.c_str());
}
}
} catch ( error_already_set ) {
PyErr_Print();
}
Py_Finalize();
}
So now lets try it:
>>> import PyHelloWorld
0>>> a = PyHelloWorld.getDerivedClassA()
0>>> b = PyHelloWorld.getDerivedClassB()
0>>> print a.speak()
Derived Class A
0>>> print b.speak()
Derived Class B
0>>>
No comments:
Post a Comment