我有一个Python类,它派生自C ++类并覆盖部分函数。 C ++函数接收Python类的对象并将其存储在向量中,因此GC不应收集Python类。我尝试了两种不同的方法,但第一种方法没有编译,第二种方法在运行时没有看到覆盖(调用C ++的函数而不是Python类函数)。请告诉我这样做的正确方法。
C ++代码:
class MyClass
{
public:
virtual void PureVirtual(int i) = 0;
virtual const char* VirtualWithDefaultImpl()
{
return "MyClass";
}
};
void MyFnc(boost::shared_ptr<MyClass> obj)
{
myVector.push_back(obj);
std::cout << obj->VirtualWithDefaultImpl() << std::endl;
obj->PureVirtual(0);
}
python包装器:
class MyClassWrap : public MyClass, wrapper<MyClass>
{
public:
MyClassWrap(PyObject* self) : m_self(self)
{
Py_INCREF(self);
}
MyClassWrap(PyObject* self, const MyClass& other) : MyClass(other), m_self(self)
{
Py_INCREF(self);
}
~MyClassWrap()
{
Py_DECREF(m_self);
}
virtual void PureVirtual(int i)
{
this->get_override("PureVirtual")(i);
}
virtual const char* VirtualWithDefaultImpl()
{
if (override f = this->get_override("VirtualWithDefaultImpl"))
return f();
return MyClass::VirtualWithDefaultImpl();
}
const char* DefaultVirtualWithDefaultImpl()
{
return this->MyClass::VirtualWithDefaultImpl();
}
private:
PyObject* m_self;
};
BOOST_PYTHON_MODULE(MyModule)
{
// First approach:
// Fails in compilation with error C2243: 'type cast' : conversion from
// 'MyClassWrap *' to 'boost::python::wrapper<T> *' exists, but is inaccessible
//class_<MyClassWrap, boost::shared_ptr<MyClassWrap>, boost::noncopyable>("MyClass")
// Second approach:
// Doesn't see the overrides at runtime
class_<MyClass, boost::shared_ptr<MyClassWrap>, boost::noncopyable>("MyClass")
.def("PureVirtual", pure_virtual(&MyClass::PureVirtual), args("i"))
.def("VirtualWithDefaultImpl", &MyClass::VirtualWithDefaultImpl,
&MyClassWrap::DefaultVirtualWithDefaultImpl);
def("MyFnc", &MyFnc, args("obj"));
}
Python代码:
class PythonDerived(MyModule.MyClass):
def PureVirtual(self, i):
print i
def VirtualWithDefaultImpl(self):
return 'PythonDerived'
MyModule.MyFnc(PythonDerived())
第二种方法的输出。如您所见,调用MyClass的函数而不是PythonDerived函数:
MyClass
File "z:\tmp\tmp.py", line 11, in <module>
MyModule.MyFnc(PythonDerived())
TypeError: 'NoneType' object is not callable
答案 0 :(得分:0)
我修改了你的包装器类以及它如何暴露给python,现在它正在按预期工作:
class MyClassWrap : public MyClass, public python::wrapper<MyClass>
{
public:
MyClassWrap() : MyClass()
{
}
virtual void PureVirtual(int i)
{
this->get_override("PureVirtual")(i);
}
virtual const char* VirtualWithDefaultImpl()
{
if (python::override f = this->get_override("VirtualWithDefaultImpl"))
return f();
return MyClass::VirtualWithDefaultImpl();
}
const char* DefaultVirtualWithDefaultImpl()
{
return this->MyClass::VirtualWithDefaultImpl();
}
};
BOOST_PYTHON_MODULE(MyModule)
{
python::class_<MyClassWrap, boost::shared_ptr<MyClassWrap>, boost::noncopyable>("MyClass")
.def("PureVirtual", python::pure_virtual(&MyClassWrap::PureVirtual), python::args("i"))
.def("VirtualWithDefaultImpl", &MyClassWrap::VirtualWithDefaultImpl,
&MyClassWrap::DefaultVirtualWithDefaultImpl);
python::def("MyFnc", &MyFnc, python::args("obj"));
}
输出:
PythonDerived
0