Reputation: 2156
I am working on exposing some existing C++ code to Python.
I have a virtual class:
class SomeVirtualClass {
public:
SomeVirtualClass();
virtual ~SomeVirtualClass();
virtual SomeVirtualClass *clone() const = 0;
virtual SomeVirtualClassType getType() const = 0;
// SomeVirtualClassType is a descriptive enum
virtual std::string getSomeString() const = 0;
private:
//some other things here
}
and a class that makes use of the virtual type:
class A {
public:
SomeVirtualClass getThisThing();
}
I need to be able to use getThisThing
from A in python. The method can return one of a number of classes derived from SomeVirtualClass. Using the boost doc and several similar stackoverflow questions, I have come up with:
namespace bp = boost::python
class SomeVirtualClassWrap : public SomeVirtualClass,
public bp::wrapper<SomeVirtualClass> {
public:
std::string getSomeString() {
return this->get_override("getSomeString")();
}
SomeVirtualClass *clone() {
return this->get_override("clone")();
}
SomeVirtualClassType getType() {
return this->get_override("getType")();
}
};
As a wrapper for the virtual class and:
bp::class_ <SomeVirtualClassWrap, boost::noncopyable>("SomeVirtualClass", no_init)
.def("GetSomeString", bp::pure_virtual(&SomeVirtualClass::getSomeString))
.def("Clone", bp::pure_virtual(&SomeVirtualClass::clone))
.def("GetType", bp::pure_virtual(&SomeVirtualClass::getType));
As the python exposure.
for reference Class A is also exposed:
bp::class_<A>("A") {
.def("GetThisThing", &A::getThisThing)
}
When I try to compile I get:
error: cannot declare field 'boost::python::objects::value_holder<SomeVirtualClassWrap>::m_held' to be of abstract type 'SomeVirtualClassWrap'
src/lib/objects/sub_mtrl/rebarmodule.c:412:7: note: because the following virtual functions are pure within 'SomeVirtualClassWrap':
ThisIsAHeader.h:42:27: note: virtual SomeVirtualClass* SomeVirtualClass::clone() const
ThisIsAHeader.h:43:30: note: virtual SomeVirtualClassType SomeVirtualClass::getType() const
ThisIsAHeader.h:44:25: note: virtual std::string SomeVirtualClass::getSomeString() const
In file included from tools/boost-for-sds2-2016/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:47:0,
from tools/boost-for-sds2-2016/include/boost/python/object/value_holder.hpp:50,
from tools/boost-for-sds2-2016/include/boost/python/object/class_metadata.hpp:11,
from tools/boost-for-sds2-2016/include/boost/python/class.hpp:23,
from tools/boost-for-sds2-2016/include/boost/python.hpp:18
I need to be able to call A.GetThisThing() from Python and handle the object. I would prefer to leave the existing code as is, if at all possible.
EDIT: As per the comment, I added no_init to the python exposure code and the error about pure methods cleared up. Now I am left with:
error: no match for call to '(const boost::python::detail::specify_a_return_value_policy_to_wrap_functions_returning<SomeVirtualClass*>) (SomeVirtualClass*)
EDIT: Removing the *clone method from the Python exposure cleared that error up. Turns out I didn't need that one anyway. Just working on a conversion error.
Upvotes: 0
Views: 360
Reputation: 2156
As per Luka Rahne's comment, adding no_init fixed the compilation error:
bp::class_ <SomeVirtualClassWrap, boost::noncopyable>("SomeVirtualClass", no_init)
.def("GetSomeString", bp::pure_virtual(&SomeVirtualClass::getSomeString))
.def("Clone", bp::pure_virtual(&SomeVirtualClass::clone))
.def("GetType", bp::pure_virtual(&SomeVirtualClass::getType));
Special shout out to n.m. as well.
Upvotes: 1