Cython - 如何正确调用带引用的运算符

时间:2016-06-11 16:12:13

标签: python c++ cython

我在C ++代码的Cython包装器中有以下代码:

# 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

但是,我从来没有想过如何正确调用mul_mm方法。它一直说Cannot convert 'SymbolicMonomial' to Python object,反之亦然。事情是我需要能够以这种方式繁殖两个SymMonomials。但是出于某种原因,我无法理解如何正确地做到这一点。有什么建议吗?

1 个答案:

答案 0 :(得分:1)

您有很多问题:

  1. 您无法直接将C ++对象返回给Python - 您需要返回包装器类型(分配给包装器的thisptr

  2. 在调用函数时,您无法保证selfother的类型正确(请参阅http://docs.cython.org/src/userguide/special_methods.html#arithmetic-methods中有关方法的说明以任一顺序调用操作数)。要使用Cython类的C / C ++成员,您需要确保Cython知道该对象确实属于该类。我建议使用<Classname?>样式转换(注意问号),如果它不匹配则抛出异常。

  3. 您还需要从thisptr获取other,而不是仅仅将Python包装类传递给C ++函数。

  4. 以下情况应该有效。

    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