我试图通过继承扩展Python中现有的C++对象。 我可以成功地做到这一点,并运行Python中重写的虚拟方法。然而,当我尝试将Python对象添加到C++基础对象类型的指针列表中时(Python类已经重写的基础对象),我会得到一个类型错误:“尝试追加一个无效类型”
我确信这个错误是由于没有从deriver*到base*的begin“隐式\u convertible”功能造成的。在C++中,这将被定义为:SimulyLyTyl& Lt[[派生-Fas-Base] ] ,基< EEM> Gt;;())。 可以用python定义它吗?在
我怎样才能做到这一点?在
下面是复制此行为的示例代码。在
C++ +<
struct Base {
virtual ~Base() {}
virtual int f() = 0;
};
struct A {
std::vector<Base*>& GetBaseList() { return m_base_List; }
std::vector<Base*> m_base_List;
};
struct BaseWrap : Base, wrapper<Base> {
int f() { return this->get_override("f")(); }
};
BOOST_PYTHON_MODULE(sandbox)
{
class_<BaseWrap, Base*, boost::noncopyable>("Base", no_init)
.def("f", pure_virtual(&Base::f));
class_<A, A*>("A", init<>())
.add_property("baseList", make_function(&A::GetBaseList, return_internal_reference<>()));
//implicitly_convertible<[Derived_from_base]*,Base*>();
class_<std::vector<Base*>>("BaseList").def(vector_indexing_suite<std::vector<Base*>>());
}
Python 从sandbox导入*
^{pr2}$任何帮助或想法将不胜感激。在
BaseList.append()
函数接收一个右类型的参数;但是,该参数具有不适当的值。在Python中,derived
初始值设定项没有初始化其层次结构的sandbox.Base
部分。这会导致Boost.Python对象,不包含C++ +{< CD4}}对象。因此,当{{CD1}}试图提取C++ ^ {< CD4}}对象时,它失败并引发错误。在要解决此问题,请在
^{pr2}$derived.__init__()
中显式调用Base.__init__()
:但是,尝试这样做会暴露
BaseWrap
的其他问题:sandbox.Base
类必须可以从Python构造,因此绑定不能提供boost::python::no_init
作为其初始值设定项规范。通常,当C++对象被从C++显式实例化并传递到Python时,只需要使用^ {CD11}},例如通过工厂函数。在T
为BaseWrap
时,Base*
的HeldType
不能满足{HeldType
必须是:BaseWrap
,它是从BaseWrap
派生的类,或者是{可以通过如下方式公开类来解决这些问题:
这里是一个完整的例子demonstrating,它传递一个从C++暴露类派生到C++向量的对象,该向量通过^ {}:
交互式使用:
对于集合和指针,通常有一些注意事项。在这种情况下:
BaseList
对象没有其元素所引用的对象的共享所有权。请注意确保容器引用的对象的生存期至少与容器本身一样长。在上面的例子中,如果对象d
被删除,那么调用base_list[0].perform()
会导致未定义的行为。在base_list
进行迭代,因为迭代器的值将尝试执行base*
-到Python的转换,这是不存在的。在上面的例子也展示了功能调度的区别。如果Python可以直接调用方法,那么它将使用自己的方法解析机制来调用方法。注意}如何返回不同的值,因为其中一个通过操纵结果的
base_list[0].perform()
和{base_wrap::perform()
进行调度,而另一个则没有。在在原始代码中:
由于Python知道
derived.f()
,调用d.f()
将不会通过BaseWrap::f()
进行调度。如果调用了BaseWrap::f()
,那么它将被抛出,因为derived.f()
返回了None
,这将无法转换为int
:相关问题 更多 >
编程相关推荐