问题
How do I access derived class in python from abstract class(interface class) without exposing derived class, by only exposing abstract class. I do not want to expose derived class for python. Is there any way that I can access derived class through abstract class? The example code is:
Base.h
class Base
{
public:
virtual void Set(const std::vector<std::string>& AllParameters) = 0;
};
struct BaseWrap : Base, wrapper<Base>
{
void Set(const std::vector<std::string>& AllParameters)
{
this->get_override("Set")(AllParameters);
}
}
Base.cpp
BOOST_PYTHON_MODULE(Example)
{
class_<Basewrapper , boost::noncopyable> ("Base")
.def("Set",pure_virtual(&Base::Set))
;
}
Derived.h
class Derived : public Base
{
public:
void Set(const std::vector<std::string>& AllParameters);
int test(int a, int b);
};
Derived.cpp
void Derived::Set(const std::vector<std::string>& AllParameters)
{
//some code here
}
void Derived:: test(int a , int b)
{
return a+b;
}
回答1:
As far as I know, there is no way to access a class without exposing the class. Boost.Python requires the static types to be exposed. However, it is possible to obtain virtual function resolution to instance whose dynamic type has not been exposed through Boost.Python, as long as the static type has been exposed. For example, if:
Base
andBase::foo()
exposed to Boost.PythonDerived
inherits fromBase
Derived
overridesBase::foo()
Then a handle to an instance of Derived
can be passed through Boost.Python with a static type of Base*
or Base&
, and invoking foo()
on the resulting Python object will resolve to Derived::foo()
.
Here is a complete code example:
#include <boost/python.hpp>
struct Base
{
virtual int foo() = 0;
virtual ~Base() {}
};
struct Derived
: public Base
{
int foo()
{
return 42;
}
};
/// @brief Factory method to create Derived objects, but return as
/// Base*. If the instance was returned as a Derived*, then
/// Derived would need to be directly exposed to Boost.Python.
Base* make_derived()
{
return new Derived;
}
namespace python = boost::python;
/// @brief Wrapper that will provide a non-abstract type for Base.
struct BaseWrap
: public Base, public python::wrapper<Base>
{
int foo()
{
return this->get_override("foo")();
}
};
BOOST_PYTHON_MODULE(example)
{
// Exposes BaseWrap in Python as Base. This also causes C++ Base to be
// indirectly exposed for conversions via Boost.Python's wrapper.
python::class_<BaseWrap, boost::noncopyable>("Base")
.def("foo", python::pure_virtual(&Base::foo))
;
// Make an instance of Derived, but return the instance as Base*. As
// Base is indirectly exposed via the wrapper, a handle to the object
// is passed through the Boost.Python layer.
python::def("make_derived", &make_derived,
python::return_value_policy<python::manage_new_object>());
}
Interactive usage:
>>> import example
>>> d = example.make_derived()
>>> d.foo()
42
>>> class Spam(example.Base):
... def foo(self):
... return 101
...
>>> s = Spam()
>>> s.foo()
101
来源:https://stackoverflow.com/questions/20221082/how-to-access-derived-class-object-from-abstract-class-in-boost-python