我有一个C ++类实现,我想用Cython向Python公开。 类接口是这样的(每个运算符的实现涉及一些私有属性,因此它们不能是内联实现):
class Quantity {
private:
// Some implementation --
public:
explicit Quantity(...);
Quantity(const Quantity &);
~Quantity(){};
double operator()(const std::string) const;
friend Quantity operator+ (const Quantity & a, const Quantity & b) {//implementation };
friend Quantity operator- (const Quantity & a, const Quantity & b) {//implementation};
friend Quantity operator* (const Quantity & a, const Quantity & b) {//implementation};
friend Quantity operator/ (const Quantity & a, const Quantity & b) {//implementation};
friend bool operator < (const Quantity & a, const Quantity & b) {//implementation};
friend bool operator <= (const Quantity & a, const Quantity & b) {//implementation};
friend bool operator > (const Quantity & a, const Quantity & b) {//implementation};
friend bool operator >= (const Quantity & a, const Quantity & b) {//implementation};
friend bool operator == (const Quantity & a, const Quantity & b) {//implementation};
friend bool operator != (const Quantity & a, const Quantity & b) {//implementation};
};
.pxd(部分):
from libcpp.string cimport string
from libcpp cimport bool
cdef extern from "quantity.h" namespace "munits":
cdef cppclass Quantity:
Quantity(...)
bool operator< (const Quantity &)
double operator()(string)
Quantity operator+(const Quantity &)
.pyx(部分):
cdef class PyQuantity:
cdef :
Quantity *_thisptr
def __cinit__(PyQuantity self, ... ):
self._thisptr = new Quantity(...)
def __cinit__(PyQuantity self, Quantity ot):
self._thisptr = new Quantity(ot)
def __dealloc__(self):
if self._thisptr != NULL:
del self._thisptr
cdef int _check_alive(self) except -1:
if self._thisptr == NULL:
raise RuntimeError("Wrapped C++ object is deleted")
else:
return 0
def __enter__(self):
self._check_alive()
return self
def __exit__(self, exc_tp, exc_val, exc_tb):
if self._thisptr != NULL:
del self._thisptr
self._thisptr = NULL # inform __dealloc__
return False # propagate exceptions
def __richcmp__(PyQuantity self, PyQuantity other, op):
if op == 0:
return self._thisptr[0] < other._thisptr[0]
def __add__(PyQuantity self, PyQuantity other):
return new PyQuantity(self._thisptr[0] + other._thisptr[0])
operator()和所有比较运算符的实现都有效,但是对于其他数学运算符,比如'+',我无法正确运行。我还检查了此处描述的变体:Cython: Invalid operand types for '+' (btVector3; btVector3) 但我仍然得到无效的操作数类型或无法将'Quantity'转换为Python对象。我错过了什么,为什么其他运营商工作和增加而不是这样?
答案 0 :(得分:0)
据我记得
,不允许多个__cinit__
def __cinit__(PyQuantity self, ... ):
self._thisptr = new Quantity(...)
def __cinit__(PyQuantity self, Quantity ot):
self._thisptr = new Quantity(ot)
__cinit__
的参数应该是python对象(object,list,tuple,int,bint,double,PyQuantity,...)而不是C ++类Quantity。
def __cinit__(PyQuantity self, PyQuantity other=None):
if other is not None:
self._thisptr = new Quantity(other._thisptr[0])
else:
self._thisptr = new Quantity()
此
def __add__(PyQuantity self, PyQuantity other):
return new PyQuantity(self._thisptr[0] + other._thisptr[0])
可能写成
def __add__(PyQuantity self, PyQuantity other):
cdef PyQuantity nobj = PyQuantity(self)
nobj._thisptr[0] += other._thisptr[0]
return nobj
答案 1 :(得分:0)
接受答案的略微修改版本确实有效。
问题是+ =未实现(出于某种原因)所以
使用nobj._thisptr[0] = self._thisptr[0] + other._thisptr[0]
,但这会导致分段错误 - 显然,因为生成的Quantity对象不是堆分隔的。
最终的实施是:
def __add__(PyQuantity self, PyQuantity other):
cdef PyQuantity nobj = PyQuantity()
nobj._thisptr = new Quantity(self._thisptr[0] + other._thisptr[0])
return nobj