2016-06-11 5 views
0

Ich habe den folgenden Code in meinem Cython Wrapper zu einem C++ Code:Cython - wie man richtig Betreiber in Verbindung mit Referenzen

# distutils: language = c++ 
# distutils: sources = symbolic.cpp 
from libcpp.vector cimport vector 
from libcpp.pair cimport pair 
from libcpp.string cimport string 
from libcpp cimport bool 

cdef extern from "symbolic.h" namespace "metadiff::symbolic": 
    cdef cppclass SymbolicMonomial: 
     vector[pair[int, int]] powers 
     long long coefficient; 
     SymbolicMonomial() 
     SymbolicMonomial(long) 
     SymbolicMonomial(const SymbolicMonomial&) 
     bool is_constant() 
     long long int eval(vector[int]&) 
     long long int eval() 
     string to_string() 
     string to_string_with_star() const 

    cdef SymbolicMonomial mul_mm"operator*"(const SymbolicMonomial&, const SymbolicMonomial&) 
    # SymbolicMonomial operator*(long long, const SymbolicMonomial&) 
    # SymbolicMonomial operator*(const SymbolicMonomial&, long long) 


cdef class SymMonomial: 
    cdef SymbolicMonomial* thisptr  # hold a C++ instance which we're wrapping 
    def __cinit__(self): 
     self.thisptr = new SymbolicMonomial() 
    def __cinit__(self, int value): 
     self.thisptr = new SymbolicMonomial(value) 
    def __dealloc__(self): 
     del self.thisptr 
    def is_constant(self): 
     return self.thisptr.is_constant() 
    def eval(self): 
     return self.thisptr.eval() 
    def __str__(self): 
     return self.to_string_with_star() 
    def to_string(self): 
     return self.thisptr.to_string().decode('UTF-8') 
    def to_string_with_star(self): 
     return self.thisptr.to_string_with_star().decode('UTF-8') 
    def __mul__(self, other): 
     return mul_mm(self.thisptr, other) 
def variable(variable_id): 
    monomial = SymMonomial() 
    monomial.thisptr.powers.push_back((variable_id, 1)) 
    return monomial 

Allerdings habe ich es nie heraus, wie richtig die mul_mm Methode aufzurufen. Es sagt weiter Cannot convert 'SymbolicMonomial' to Python object oder umgekehrt. Die Sache ist, dass ich auf diese Weise zwei SymMonomials multiplizieren kann. Aber aus irgendeinem Grund kann ich nicht verstehen, wie man es richtig macht. Irgendwelche Ratschläge?

Antwort

1

Sie haben eine Reihe von Fragen:

  1. Sie können nicht zurückkehren C++ Objekte direkt an Python - Sie Ihre Wrapper-Typ zurückgeben müssen (zuweisen thisptr der Wrapper)

  2. Sie kann nicht garantieren, dass entweder self oder other vom richtigen Typ an dem Punkt ist, an dem die Funktion aufgerufen wird (siehe den Hinweis in http://docs.cython.org/src/userguide/special_methods.html#arithmetic-methods darüber, wie die Methoden mit den Operanden in beliebiger Reihenfolge aufgerufen werden können). Um die C/C++ - Member einer Cython-Klasse zu verwenden, müssen Sie sicherstellen, dass Cython weiß, dass dieses Objekt tatsächlich von dieser Klasse ist. Ich empfehle die Verwendung der <Classname?> Formatvorlage (beachten Sie das Fragezeichen), die eine Ausnahme auslöst, wenn sie nicht übereinstimmt.

  3. Sie müssen auch thisptr von other erhalten, anstatt nur die Python-Wrapper-Klasse an Ihre C++ - Funktion zu übergeben.

Folgendes sollte funktionieren.

def __mul__(self,other): 
    cdef SymMonomial tmp = SymMonomial() 
    cdef SymMonomial self2, other2 
    try: 
     self2 = <SymMonomial?>self 
     other2 = <SymMonomial?>other 
    except TypeError: 
     return NotImplemented # this is what Python expects for operators 
         # that don't know what to do 
    tmp.thisptr[0] = mul_mm(self2.thisptr[0],other2.thisptr[0]) 
    return tmp 
+0

Hey, ich denke, dass Ihr Vorschlag einige der Probleme gelöst hat. Ich bekomme aber immer noch das: '' '/home/alex/work/c/swig_test/symbolic.h: 298: Mehrfachdefinition von' metadiff :: symbolic :: operator * (metadiff :: symbolic :: SymbolicMonomial const & , metadiff :: symbolic :: SymbolicMonomial const &) ' '' ', wegen der Umbenennung mul_mm. Hast du eine Idee, warum das passiert? Ich habe Wache in meiner Header-Datei, aber aus irgendeinem Grund scheint es, es zweimal aufzunehmen? –

+0

Eigentlich habe ich das Problem gefunden. –