一个问题是cython语法有点误导人:如果
def
-函数定义为示例(因为您的示例不是最小的,所以我创建了一个不相关的示例):
def twice(double d):
return 2.0*d
然后,参数不是作为C-double传递给这个(python)函数,而是作为一个常见的python对象传递给它。然而,早期的绑定将导致cython试图通过
__pyx_PyFloat_AsDouble
在运行时,作为调用函数的第一件事,这一切都发生在幕后,因此作为编码器,您有这种欺骗填充,您将向函数传递一个double。
然而,这种自动转换仅适用于某些类型,最重要的是
double
,则,
int
,则,
cdef
-课程等等。对于其他类型,这是不可能的,例如对于原始指针(这也意味着指向自定义cpp类的指针),没有什么
__pyx\u PyFloat\u AsDouble
。
例如
def twice(double *d):
pass
无法cythonized,因为原始指针无法自动从python对象转换/转换为python对象,这是python函数所必需的。
可以定义
cdef公司
具有原始指针的函数,因为它们不超过简单的C函数,因此
cdef twice(double *d):
pass
将编译。但是,这对您没有帮助
__cinit__
,因为它必须是
def公司
-功能。
不幸的是,Cython并没有显示代码中的所有错误,只显示它找到的第一个错误,否则它会显示
def公司
s与
Coordinate *coordinate
无效。
如何解决它?基本上你应该使用
cdef公司
-包装器类
PyCCoordinate
在签名中,然后
thisptr
-例如,对于计算:
def distance(self, PyCCoordinate coordinate):
return self.thisptr.distance(coordinate.thisptr)
这种解决方案显然不适用于对象的构造,就像在方法中一样
destination
-你必须构建一个
PyCCoordinate公司
-对象,然后才能使用它!一个可能的解决方案是有一个构造函数,它将用
本PTR
存在
NULL
,调用它并手动设置此指针,类似于
cdef class PyCCoordinate:
cdef Coordinate *thisptr
def __cinit__(self):
pass
def __dealloc__(self):
del self.thisptr
def destination(self, double bearing, double distance):
cdef PyCCoordinate res=PyCCoordinate()
res.thisptr=self.thisptr.destination(bearing, distance)
return res
另一个问题:cython(也是python)与c++不同,它不知道重载,因此不能定义两个不同的构造函数(也不能定义其中一个私有构造函数),因此必须手动进行调度,例如:
cdef class PyCCoordinate:
cdef Coordinate *thisptr
def __cinit__(self, x=None, y=None):
if x is None or y is None:#default, "private" constructor
pass #thisptr is initialized to NULL
else:
self.thisptr = new Coordinate(x,y) #
def __dealloc__(self):
del self.thisptr
def destination(self, double bearing, double distance):
cdef PyCCoordinate res=PyCCoordinate()
res.thisptr=self.thisptr.destination(bearing, distance)
return res