how to access derived class object from abstract class in boost python

血红的双手。 提交于 2019-12-24 12:40:18

问题


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 and Base::foo() exposed to Boost.Python
  • Derived inherits from Base
  • Derived overrides Base::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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!