Cython 指针继承
Cython Pointer Inheritance
问题
我有一个基础 class LinkPredictor
和一个从 C++
中的 LinkPredictor
派生的子 class KatzIndex
。
现在我有另一个 class,它的构造函数中需要一个指向 LinkPredictor
.
的指针
我想将那些 class 包装在 Cython
中,以便在 Python
中可用。
我的尝试
菲律宾共产党:
class LinkPredictor { ... }
class KatzIndex : public LinkPredictor { ... }
class KFoldCrossValidator {
public:
KFoldCrossValidator(LinkPredictor* lp) { ... }
}
赛通:
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 接受类型为 _LinkPredictor*
的 _this
作为 _KatzIndex
派生自 _LinkPredictor
。但好像不是这样。
你对此有何看法?
你的问题是你的 python 基础 class (LinkPredictor) 的包装器需要包含一个指针成员,然后它可以被派生的 classes 覆盖。
举个例子,我们正在包装以下 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
问题
我有一个基础 class LinkPredictor
和一个从 C++
中的 LinkPredictor
派生的子 class KatzIndex
。
现在我有另一个 class,它的构造函数中需要一个指向 LinkPredictor
.
我想将那些 class 包装在 Cython
中,以便在 Python
中可用。
我的尝试
菲律宾共产党:
class LinkPredictor { ... }
class KatzIndex : public LinkPredictor { ... }
class KFoldCrossValidator {
public:
KFoldCrossValidator(LinkPredictor* lp) { ... }
}
赛通:
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 接受类型为 _LinkPredictor*
的 _this
作为 _KatzIndex
派生自 _LinkPredictor
。但好像不是这样。
你对此有何看法?
你的问题是你的 python 基础 class (LinkPredictor) 的包装器需要包含一个指针成员,然后它可以被派生的 classes 覆盖。
举个例子,我们正在包装以下 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