如何在Boost Python中访问抽象类的派生类对象 [英] how to access derived class object from abstract class in boost python

查看:84
本文介绍了如何在Boost Python中访问抽象类的派生类对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何仅通过暴露抽象类而从抽象类(接口类)访问python中的派生类而不暴露派生类。我不想公开python的派生类。有什么方法可以通过抽象类访问派生类?示例代码为:



Base.h

  class Base 
{
public:
virtual void Set(const std :: vector< std :: string>& AllParameters)= 0;
};

结构体BaseWrap:Base,wrapper< Base>
{
void Set(const std :: vector< std :: string>& AllParameters)
{
this-> get_override( Set)(AllParameters);
}
}

Base.cpp

  BOOST_PYTHON_MODULE(示例)
{
class_< Basewrapper,boost :: noncopyable> ( Base)
.def( Set,pure_virtual(& Base :: Set))
;
}

Derived.h

  class派生: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)
{
//此处有些代码

}

void派生:: test(int a,int b)
{
return a + b;
}


解决方案

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




  • Base Base: :foo()暴露于Boost.Python

  • 派生继承自 Base

  • 派生覆盖 Base :: foo()



然后可以传递 Derived 实例的句柄Boost.Python,其静态类型为 Base * Base& ,并调用 foo( )转换为 Derived :: foo()



下面是完整的代码示例:

  #include< boost / python.hpp> 

结构基数
{
virtual int foo()= 0;
virtual〜Base(){}
};

结构派生
:public Base
{
int foo()
{
return 42;
}
};

/// @brief工厂方法创建派生对象,但返回为
/// Base *。如果实例作为Derived *返回,则
/// Derived必须直接暴露给Boost.Python。
Base * make_derived()
{
返回新的Derived;
}

命名空间python = boost :: python;

/// @brief包装器,它将为Base提供非抽象类型。
struct BaseWrap
:public Base,公共python :: wrapper< Base>
{
int foo()
{
return this-> get_override( foo)();
}
};

BOOST_PYTHON_MODULE(示例)
{
//将Python中的BaseWrap公开为Base。这也导致C ++ Base通过Boost.Python的包装器间接为转换提供
//。
python :: class_< BaseWrap,boost :: noncopyable>( Base)
.def( foo,python :: pure_virtual(& Base :: foo))
;

//创建一个Derived实例,但将该实例返回为Base *。由于
//通过包装程序间接暴露了Base,因此对象
//的句柄通过Boost.Python层传递。
python :: def( make_derived,& make_derived,
python :: return_value_policy< python :: manage_new_object>());
}

交互式用法:



< pre class = lang-python prettyprint-override> >>>导入示例
>>> d = example.make_derived()
>>> d.foo()
42
>> class Spam(example.Base):
... def foo(self):
...返回101
...
>> s = Spam()
>> s.foo()
101


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; 
}

解决方案

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

这篇关于如何在Boost Python中访问抽象类的派生类对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆