Reputation: 1399
I have the following code in my Cython wrapper to a C++ code:
# 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
However, I never figured it out how to call the mul_mm
method correctly. It keeps saying Cannot convert 'SymbolicMonomial' to Python object
or vice versa. The thing is I need to be able to multiply two SymMonomials in this way. However for some reason I can not get the hang of it of how to do it properly. Any advices?
Upvotes: 0
Views: 383
Reputation: 30910
You have a number of issues:
You can't return C++ objects directly to Python - you need to return your wrapper type (assign to thisptr
of the wrapper)
You can't guarantee either self
or other
is of the correct type at the point the function is called (see the note in http://docs.cython.org/src/userguide/special_methods.html#arithmetic-methods about how the methods can be called with the operands in either order). To use the C/C++ members of a Cython class you need to ensure Cython knows that object is indeed of that class. I recommend using the <Classname?>
style cast (note the question mark) which throws an exception if it doesn't match.
You need to get thisptr
from other
too, rather than just passing the Python wrapper class to your C++ function.
The following should work.
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
Upvotes: 1