I'm trying to expose my C++ Classes to Python using Boost.Python. Here is a simplyfied version of what I'm trying to do:
struct Base {virtual ~Base() {};virtual char const *Hello() {printf("Base.Hello\n");return "Hello. I'm Base.";};
};struct Derived : Base {char const *Hello() {printf("Derived.Hello\n");return "Hello. I'm Derived.";};Base &test() {printf("Derived.test\n");// ...// After some calculation, we get result reference `instance'// `instance' can be an instance of Base or Derived.// ...return instance;}
};
I want to use above classes as follows in python:
instance = Derived()// If method test returns an instance of Base
instance.test().Hello() // Result: "Hello. I'm Base."// If method test returns an instance of Derived
instance.test().Hello() // Result: "Hello. I'm Derived."
I didn't know any nice solution to this problem. I just tried this:
struct BaseWrapper : Base, wrapper<Base> {char const *Hello() {printf("BaseWrapper.Hello\n");if (override Hello = this->get_override("Hello")) {return Hello();}return Base::Hello();}char const *default_Hello() {printf("BaseWrapper.default_Hello\n");return this->Base::Hello();}
};struct DerivedWrapper : Derived, wrapper<Derived> {char const *Hello() {printf("DerivedWrapper.Hello\n");if (override Hello = this->get_override("Hello")) {return Hello();}return Derived::Hello();}char const *default_Hello() {printf("DerivedWrapper.default_Hello\n");return this->Derived::Hello();}Base &test() {printf("DerivedWrapper.test\n");if (override Hello = this->get_override("test")) {return Hello();}return Derived::test();}Base &default_test() {printf("DerivedWrapper.default_test\n");return this->Derived::test();}
};
And them, I use following code:
BOOST_PYTHON_MODULE(Wrapper) {class_<BaseWrapper, boost::noncopyable>("Base").def("Hello", &Base::Hello, &BaseWrapper::default_Hello);class_<DerivedWrapper, boost::noncopyable, bases<Base> >("Derived").def("Hello", &Derived::Hello, &DerivedWrapper::default_Hello).def("test", &Derived::test, return_value_policy<copy_non_const_reference>());
}
But when I compiled above code into a .so file, and used in python
derived = Wrapper.Derived()
derived.test()
It throws out an exception:
TypeError: No to_python (by-value) converter found for C++ type: Base
This post has the same error as mine, but in a different way, it didn't help me a lot. Boost.Python call by reference : TypeError: No to_python (by-value) converter found for C++ type:
This post solves a similar problem, but didn't help me either. https://github.com/BVLC/caffe/issues/3494
I have two problems:
- If the way I tried is the right way, how to solve the TypeError problem?
- If I tried a wrong way, then what is the best way to solve the problem using boost.python?