cython-cdef类c方法:如何从另一个cython-cdef类调用它而无需python开销?

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

我试图在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,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]