如何从boost python中的抽象类访问派生类对象

时间:2013-11-26 15:21:33

标签: c++ abstract-class boost-python

如何通过暴露抽象类来从抽象类(接口类)访问python中的派生类,而不暴露派生类。我不想暴露python的派生类。有没有办法可以通过抽象类访问派生类?示例代码是:

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 个答案:

答案 0 :(得分:4)

据我所知,没有暴露就无法访问。 Boost.Python需要公开静态类型。但是,只要静态类型已暴露,就可以获得虚拟函数解析到其动态类型尚未通过Boost.Python公开的实例。例如,如果:

  • BaseBase::foo()暴露于Boost.Python
  • Derived继承自Base
  • Derived会覆盖Base::foo()

然后,Derived实例的句柄可以通过Boost.Python传递,其静态类型为Base*Base&,并在生成的Python上调用foo()对象将解析为Derived::foo()

这是一个完整的代码示例:

#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>());
}

交互式使用:

>>> import example
>>> d = example.make_derived()
>>> d.foo()
42
>>> class Spam(example.Base):
...     def foo(self):
...         return 101
... 
>>> s = Spam()
>>> s.foo()
101