cython-cdef类c方法:如何从另一个cython-cdef类调用它而无需python开销?
我试图在cython中实现一个通用排序算法。因此,我创建了以下模块,该模块在类cython-cdef类c方法:如何从另一个cython-cdef类调用它而无需python开销?,python,class,interface,cython,Python,Class,Interface,Cython,我试图在cython中实现一个通用排序算法。因此,我创建了以下模块,该模块在类sorter\t中实现Heapsort算法: # file general_sort_c.pyx from libc.stdint cimport int32_t cdef bint bint_true = 1 cdef bint bint_false = 0 cdef class sorter_t: cdef object sortable_object def __init__(self,s
sorter\t
中实现Heapsort算法:
# file general_sort_c.pyx
from libc.stdint cimport int32_t
cdef bint bint_true = 1
cdef bint bint_false = 0
cdef class sorter_t:
cdef object sortable_object
def __init__(self,sortable_object):
self.sortable_object = sortable_object
cpdef sort_c(self):
"""
https://en.wikipedia.org/wiki/Heapsort
"""
cdef int32_t end
cdef int32_t count = self.sortable_object.num_elements_int32
self.heapify_c(count)
end = count-1
while end > 0:
self.sortable_object.swap_c(0,end)
end = end - 1
self.siftDown_c(0,end)
cdef heapify_c(self,int32_t count):
cdef int32_t start = (count - 2)/2
while start >= 0:
self.siftDown_c(start, count-1)
start -= 1
cdef siftDown_c(self,int32_t start, int32_t end):
cdef int32_t root = start
cdef int32_t swap
cdef int32_t child
while root * 2 + 1 <= end:
child = root * 2 + 1
swap = root
# if "swap" < "child" then ...
if self.sortable_object.lt_c(swap,child) == 1:
swap = child
if child+1 <= end and self.sortable_object.lt_c(swap,child+1) == 1:
swap = child + 1
if swap != root:
self.sortable_object.swap_c(root,swap)
root = swap
else:
return
编译.pyx
两个文件并在IPython控制台中运行以下命令后,出现以下错误:
In [1]: import test_general_sort_c as tgs
In [2]: tgs.probar()
...
general_sort_c.sorter_t.siftDown_increasing_c (general_sort_c.c:1452)()
132
133 #if mv_tnet_time[swap] < mv_tnet_time[child]:
--> 134 if self.sortable_object.lt_c(swap,child) == bint_true:
135 swap = child
136
AttributeError: 'test_general_sort_c.sortable_t' object has no attribute 'lt_c'
[1]中的:将测试\u常规\u排序\u c作为tgs导入
在[2]中:tgs.probar()
...
通用分拣机siftDown递增分拣机(通用分拣机c:1452)()
132
133#如果mv#t#u时间[交换]134如果self.sortable_object.lt_c(swap,child)==bint_true:
135交换=子
136
AttributeError:“test\u general\u sort\u c.sortable\u t”对象没有属性“lt\u c”
因此,问题是从模块
general\u sort\u c.pyx
中的代码看不到函数lt\u c
的实现。如果我使用cpdef
而不是cdef
来定义函数lt_c
,它会起作用,但是会有很多Python开销。如何以cdef
(“纯C”)的方式调用此函数?不幸的是,我不知道如何使其与融合类型一起工作,但其余的都很简单:
test\u general\u sort\u c.pyx
需要一个免费的test\u general\u sort\u c.pxd
:
from libc.stdint cimport int32_t
cdef class sortable_t:
cdef public int32_t num_elements_int32
cdef int32_t [:] mv_lista
cdef public bint lt_c(self, int32_t left, int32_t right)
cdef public bint gt_c(self, int32_t left, int32_t right)
cdef public swap_c(self, int32_t left, int32_t right)
general\u sort\u c.pyx
然后必须cimport
test\u general\u sort\u c
并键入其self.sortable\u对象
作为test\u general\u sort\u t
当然,如果您可以有多种受支持的类型,这会更好。不过,我不知道你现在会怎么做
此外,内置的
True
和False
自身工作正常
如果你再信任Cython一点,你就会意识到你可以写作
cdef public bint lt_c(self, int32_t left, int32_t right):
return self.mv_lista[left] < self.mv_lista[right]
cdef public bint gt_c(self, int32_t left, int32_t right):
return self.mv_lista[left] > self.mv_lista[right]
cdef public swap_c(self, int32_t left, int32_t right):
self.mv_lista[right], self.mv_lista[left] = self.mv_lista[left], self.mv_lista[right]
cdef公共bint lt_c(self,int32_t left,int32_t right):
返回self.mv_lista[左]self.mv_lista[右]
cdef公共交换c(自、int32左、int32右):
self.mv_lista[右]、self.mv_lista[左]=self.mv_lista[左]、self.mv_lista[右]
很好。:) 谢谢Veedrac,成功了:)。一个问题。在您的方法中,general_sort_c cimport test_general_sort_c具有针对swap_c和lt_c的特定实现。这是否与一般可排序的objet类型兼容?如果我有多个可排序对象类型怎么办?唯一的解决方案是子类化。创建一个所有文件都“同意”的超类,接受该类的一个实例,并使可排序对象从该类继承。这不是Python级别的动态,但请记住,我们正在编译到C。我想添加一些注释。上面的代码无法正常工作,因为heapsort代码不好。我用快速排序算法重新实现了这个东西。此外,此代码是对更复杂代码的简化,如果您尝试此代码,可能会出现一些不一致的情况。不管怎样,我相信大家都理解了这个想法。顺致敬意,
cdef public bint lt_c(self, int32_t left, int32_t right):
return self.mv_lista[left] < self.mv_lista[right]
cdef public bint gt_c(self, int32_t left, int32_t right):
return self.mv_lista[left] > self.mv_lista[right]
cdef public swap_c(self, int32_t left, int32_t right):
self.mv_lista[right], self.mv_lista[left] = self.mv_lista[left], self.mv_lista[right]