2016-08-02 103 views
2

我有一個C++類實現,我想用Cython公開Python。 類的接口是這樣的(每個運營商的實施涉及到一些私有屬性,使他們不能內嵌實現):Cython:無效的操作數類型

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]) 

操作員()和所有的比較操作工作,但對於其它數學運算符象實現「+」,我不能得到它的權利。我也檢查了這裏描述的變化:Cython: Invalid operand types for '+' (btVector3; btVector3) 但我仍然收到無效操作數類型或無法將'數量'轉換爲Python對象。我錯過了什麼,爲什麼其他操作員工作和添加等不?

+0

在您所提供的鏈接,答案在.pxd('數量運營商+(數量)')不使用引用,你嘗試了嗎? – Holt

回答

0

__cinit__沒有,據我記得

def __cinit__(PyQuantity self, ...): 
    self._thisptr = new Quantity(...) 

def __cinit__(PyQuantity self, Quantity ot): 
    self._thisptr = new Quantity(ot) 

參數傳遞給__cinit__應該是Python對象允許的(對象,列表,元組,INT,賓特,雙,PyQuantity,......),而不是一C++類的數量​​。

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 
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