【问题标题】:Cython: invalid operand typesCython:无效的操作数类型
【发布时间】:2016-08-02 07:12:00
【问题描述】:

我有一个 C++ 类实现,我想用 Cython 向 Python 公开。 类接口是这样的(每个算子的实现都涉及到一些私有属性,所以不能内联实现):

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

operator() 和所有比较运算符的实现都可以工作,但对于像“+”这样的其他数学运算符,我无法正确理解。我还检查了这里描述的变化:Cython: Invalid operand types for '+' (btVector3; btVector3) 但我仍然得到无效的操作数类型或无法将“数量”转换为 Python 对象。我错过了什么,为什么其他运算符可以工作和加法等等?

【问题讨论】:

  • 在您提供的链接中,答案在 .pxd (Quantity operator+(Quantity)) 中没有使用引用,您尝试过吗?

标签: python c++ cython


【解决方案1】:

据我所知,不允许使用多个__cinit__

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

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

__cinit__ 的参数应该是 python 对象(object、list、tuple、int、bint、double、PyQuantity、...),而不是 C++ 类 Quantity。

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

【讨论】:

    【解决方案2】:

    已接受答案的略微修改版本实际上有效。 问题是 += 没有实现(出于某种原因)所以 使用了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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-07
      • 2013-01-25
      • 1970-01-01
      • 1970-01-01
      • 2013-05-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多