以下C ++代码脱离了标准的Cython矩形示例,添加了任意一个" +"操作者:
#include "Rectangle.h"
using namespace shapes;
Rectangle::Rectangle(int X0, int Y0, int X1, int Y1)
{
x0 = X0;
y0 = Y0;
x1 = X1;
y1 = Y1;
}
Rectangle::~Rectangle() {}
int Rectangle::getLength()
{
return (x1 - x0);
}
Rectangle operator+(const Rectangle &r1, const Rectangle &r2)
{
return Rectangle(r1.X0 + r2.X0, r1.Y0 + r2.Y0, r1.X1 + r2.X1, r1.Y1 + r2.Y1)
}
这与Cython C ++类定义有关:
cdef extern from "Rectangle.h" namespace "shapes":
cdef cppclass Rectangle:
Rectangle(int, int, int, int) except +
int x0, y0, x1, y1
int getLength()
Rectangle operator+(Rectangle) nogil
我们解决这个问题的唯一方法是使用以下Cython代码:
cdef class PyRectangle:
cdef Rectangle *thisptr # hold a C++ instance which we're wrapping
def __cinit__(self, int x0=0, int y0=0, int x1=0, int y1=0):
if x0 == 0:
self.thisptr = NULL
else:
self.thisptr = new Rectangle(x0, y0, x1, y1)
def __dealloc__(self):
del self.thisptr
def getLength(self):
return self.thisptr.getLength()
def __add__(self, other):
cdef Rectangle rect = deref(self.thisptr) + deref(other.thisptr)
cdef Rectangle* ptr_rect = new Rectangle(rect.x0, rect.y0, rect.x1, rect.y1)
ret = PyRectangle()
ret.thisptr = ptr_rect
return ret
这不是最优的,因为我们在__add__
中有一个额外的副本,而且代码也不是很简单/短。这是用于包装外部库,因此我们不能简单地将任何新构造函数定义为Rectangle,并且我们无法在Cython级别重写添加。
我们认为我们可以简单地写一下:
ret = PyRectangle()
deref(ret.thisptr) = deref(self.thisptr) + deref(other.thisptr)
return ret
但是这会给出错误"无法分配或删除它。"
在Cython中有更优选的方法吗?我们发现的解决方案在我们的代码中不可行。
答案 0 :(得分:3)
对于指针,x[0]
与deref(x)
相同,因此您可以改为编写
ret.thisptr[0] = self.thisptr[0] + other.thisptr[0]
另请注意,如果被包装的对象具有无效构造函数,则根本不需要指针,只需执行
cdef class PyRectangle:
cdef Rectangle c_rect
def __init__(self, int x0=0, int y0=0, int x1=0, int y1=0):
self.c_rect = Rectangle(x0, y0, x1, y1)
# no __dealloc__ needed
def __add__(PyRectangle left, PyRectangle right):
PyRectangle ret = PyRectangle()
ret.c_rect = left.c_rect + right.c_rect
return ret
在这种情况下我发现添加静态方法
很方便cdef class PyRectangle:
[...]
@staticmethod
cdef create(Rectangle r):
PyRectangle ret = PyRectangle()
ret.c_rect = r
return ret
然后你可以简单地做
def __add__(PyRectangle left, PyRectangle right):
return PyRectangle.create(left.c_rect + right.c_rect)