我有一个基类LinkPredictor
和一个子类KatzIndex
,它源自LinkPredictor
中的C++
。
现在我有另一个类,它在构造函数中需要一个指向LinkPredictor
的指针。
我希望将这些类包装在Cython
中,以便在Python
中使用它们。
CPP:
class LinkPredictor { ... }
class KatzIndex : public LinkPredictor { ... }
class KFoldCrossValidator {
public:
KFoldCrossValidator(LinkPredictor* lp) { ... }
}
用Cython:
cdef extern from ".../LinkPredictor.h":
cdef cppclass _LinkPredictor:
_LinkPredictor(...) except +
cdef class LinkPredictor:
def __cinit__(self):
return
cdef extern from ".../KatzIndex.h":
cdef cppclass _KatzIndex(_LinkPredictor):
_KatzIndex(...) except +
...
cdef class KatzIndex(LinkPredictor):
cdef _KatzIndex* _this
...
cdef extern from ".../KFoldCrossValidator.h":
cdef cppclass _KFoldCrossValidator:
_KFoldCrossValidator(_LinkPredictor* linkPredictor) except +
...
cdef class KFoldCrossValidator:
cdef _KFoldCrossValidator* _this
def __cinit__(LinkPredictor linkPredictor):
self._this = new _KFoldCrossValidator(linkPredictor._this)
...
上述方法无效。 Cython抛出以下错误消息:
Error compiling Cython file:
------------------------------------------------------------
...
cdef _KFoldCrossValidator* _this
def __cinit__(self, LinkPredictor linkPredictor):
self._this = new _KFoldCrossValidator(linkPredictor._this)
^
------------------------------------------------------------
.../project.pyx:X:Y: Cannot convert Python object to '_LinkPredictor *'
我认为这是因为_this
仅在KatzIndex
中声明,因此其类型为_KatzIndex*
而不是_LinkPredictor*
。现在我尝试从_LinkPredictor
和_KatzIndex
声明继承关系(通过声明_KatzIndex(_LinkPredictor)
)并希望Cython接受类型为_this
的{{1}}为{ {1}}来自_LinkPredictor*
。但事实似乎并非如此。
您对此有何看法?
答案 0 :(得分:2)
你的问题是你的基类python包装器(LinkPredictor)需要包含一个指针成员,然后可以被派生类覆盖。
举个例子说我们正在包装以下c ++库:
<强> foo.hpp 强>
class Base {
public:
virtual double a();
};
class Derived : public Base {
public:
virtual double a();
};
class Using {
public:
double a;
Using(Base *b);
};
<强> Foo.cpp中强>
#include "foo.hpp"
double Base::a()
{
return 1.0;
}
double Derived::a()
{
return 2.0;
}
Using::Using(Base *b) : a(b->a())
{}
然后我们可以将包装器写为
<强> pyfoo.pyx 强>
cdef extern from "foo.hpp":
cdef cppclass Base:
Base() except +
cdef cppclass Derived(Base):
Derived() except +
cdef cppclass Using:
Using(Base *b) except +
double a
cdef class PyBase(object):
cdef Base *_this
def __cinit__(self):
if type(self) != PyBase:
return
self._this = new Base()
def __dealloc__(self):
if self._this is not NULL:
del self._this
self._this = NULL
cdef class PyDerived(PyBase):
def __cinit__(self):
self._this = new Derived()
def __dealloc__(self):
if self._this is not NULL:
del self._this
self._this = NULL
cdef class PyUsing(object):
cdef Using *_this
def __cinit__(self, PyBase b):
self._this = new Using(b._this)
def a(self):
return self._this.a
def __dealloc__(self):
if self._this is not NULL:
del self._this
self._this = NULL
除此之外,您可能还需要阅读此tutorial