抽象C类不能以这种方式暴露给Boost.Python. Boost.Python
tutorial提供了如何公开纯虚拟函数的示例.简而言之,当使用boost :: python :: pure_virtual装饰方法时,需要创建一个包装类型,以允许C多态解析虚拟函数,虚拟函数实现将委托Python对象的层次结构中的多项解析函数.
struct BaseWrap : Base,boost::python::wrapper
{
int foo()
{
return this->get_override("foo")();
}
};
...
boost::python::class_("Base",...)
.def("foo",boost::python::pure_virtual(&Base::foo))
;
有关详细信息,当通过boost :: python :: class_公开类型时,HeldType默认为要暴露的类型,并且HeldType在Python对象中构建. class_文档规定:
Template Parameter:
T: The class being wrapped
HeldType: Specifies the type that is actually embedded in a Python object wrapping a T instance […]. Defaults to T.
因此,boost :: python :: class_< Base>将失败,因为T = Base和HeldType = Base,Boost.Python将尝试将HeldType的对象实例化为表示Base实例的Python对象.这个实例化将失败,因为Base是一个抽象类.
这是一个完整的示例,显示了使用BaseWrap类.
#include
struct Base
{
virtual int foo() = 0;
virtual ~Base() {}
};
struct Derived : public Base
{
virtual int foo()
{
return 42;
}
};
Base* get_base()
{
return new Derived;
}
namespace python = boost::python;
/// @brief Wrapper that will provide a non-abstract type for Base.
struct BaseWrap : Base,python::wrapper
{
BaseWrap() {}
BaseWrap(const Base& rhs)
: Base(rhs)
{}
int foo()
{
return this->get_override("foo")();
}
};
BOOST_PYTHON_MODULE(example)
{
python::class_("Base")
.def("foo",python::pure_virtual(&Base::foo));
;
python::def("get_base",&get_base,python::return_value_policy());
}
及其用途:
>>> import example
>>> class Spam(example.Base):
... pass
...
>>> Spam().foo()
Traceback (most recent call last):
File "",line 1,in
RuntimeError: Pure virtual function called
>>> class Egg(example.Base):
... def foo(self):
... return 100
...
>>> e = Egg()
>>> e.foo()
100
>>> d = example.get_base()
>>> d.foo()
42
在Boost.Python中暴露一个抽象类是可能的,它没有默认的初始化器(boost :: python :: no_init)和不可复制(boost :: noncopyable).缺少一个初始化器可以防止Python类型从中有效地避免重写.另外,Base :: foo()在C中由Derived实现的实现细节是无关紧要的.如果Python根本不知道一个foo()方法,那么通过def()来忽略它.
#include
struct Base
{
virtual int foo() = 0;
virtual ~Base() {}
};
struct Derived
: public Base
{
virtual int foo()
{
return 42;
}
};
struct OtherDerived
: public Base
{
virtual int foo()
{
return 24;
}
};
Base* get_base()
{
return new Derived;
}
Base* get_other_base()
{
return new OtherDerived;
}
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::class_("Base",python::no_init)
;
python::class_ >("Derived",python::no_init)
.def("foo",&Base::foo)
;
python::class_ >(
"OtherDerived",python::no_init)
;
python::def("get_base",python::return_value_policy());
python::def("get_other_base",&get_other_base,python::return_value_policy());
}
互动用途:
>>> import example
>>> b = example.get_base()
>>> b.foo()
42
>>> b = example.get_other_base()
>>> b.foo()
Traceback (most recent call last):
File "",in
AttributeError: 'OtherDerived' object has no attribute 'foo'