Question

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; 
}
Était-ce utile?

La solution

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top