2016-08-02 3 views
2

Ich habe eine C++ - Klassenimplementierung, die ich mit Cython für Python bereitstellen möchte. Die Klasse-Schnittstelle ist so etwas (jede Implementierung des Operators beinhaltet einige private Attribute, so dass sie nicht als Inline-Implementierungen sein können):Cython: ungültige Operandentypen

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 (teilweise):

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 (teilweise):

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

die Implementierung für den Betreiber() und alle Vergleichsoperatoren arbeiten, aber für andere mathematische Operatoren wie ‚+‘ kann ich es nicht richtig machen . Ich habe auch die hier beschriebenen Varianten überprüft: Cython: Invalid operand types for '+' (btVector3; btVector3) Aber ich bekomme immer noch entweder ungültige Operandentypen oder kann 'Menge' nicht in Python-Objekt konvertieren. Was vermisse ich, warum arbeiten andere Betreiber und Zusatz und so nicht?

+0

In dem Link, den Sie zur Verfügung stellen, verwenden Sie die Antwort keine Hinweise auf dem .pxd ('Menge Operator + (Anzahl)'), haben Sie versuchen das? – Holt

Antwort

0

Multiple __cinit__ ist nicht so weit wie ich

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

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

Argumente zu __cinit__ sollten Python Objekte erinnern erlaubt sein (Objekt, Liste, Tupel, int, bint, Doppel-, PyQuantity, ...) und nicht ein C++ Klasse Menge. Diese

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

wahrscheinlich geschrieben werden könnte als

def __add__(PyQuantity self, PyQuantity other): 
    cdef PyQuantity nobj = PyQuantity(self) 
    nobj._thisptr[0] += other._thisptr[0] 

    return nobj 
0

Eine leicht modifizierte Version der akzeptierte Antwort tatsächlich funktioniert. Das Problem damit war + = ist nicht implementiert (aus einem Grund), so nobj._thisptr[0] = self._thisptr[0] + other._thisptr[0] wurde verwendet, aber dies verursacht Segmentierungsfehler - offensichtlich, da das resultierende Menge Objekt nicht Heap alolocated ist. Die endgültige Umsetzung ist:

def __add__(PyQuantity self, PyQuantity other): 
     cdef PyQuantity nobj = PyQuantity() 
     nobj._thisptr = new Quantity(self._thisptr[0] + other._thisptr[0]) 
     return nobj