我想在cython代码中使用一个C++ std::priority_queue,其中每个项目应该是一个结构或一个类,但我不知道如何定义一个比较器。
如果我考虑使用一个元素是标准类型的priority_queue,一切都会好起来,就像下面的例子一样。
simple.pyx
# distutils: language = c++
cimport cython
from libcpp.queue cimport priority_queue
def testIntPriorityQueue():
cdef priority_queue[int] q
q.push(5)
q.push(15)
q.push(7)
print('q.top (after pushing 5, 15, 7) = ',q.top())
q.pop()
print('q.top (after popping one item) = ',q.top())`
main.py
import simple
def main():
simple.testIntPriorityQueue()
main()
当我执行这段代码时,在推送5、15和7之后,优先级_queue正确地将最大的(15)置顶(因为它由q.top返回),而在弹出一个元素之后,q.top返回7,在去掉15之后成为最大的。
现在我想有一个类似的行为,但推送到队列中的项目不是标准类型的对象,而是更复杂的东西。
我试着用下面的东西来定义这样一个结构。
simple. pxd
cimport cython
ctypedef struct myType:
int key
float a
float b
simple.pyx
# distutils: language = c++
cimport cython
from libc.stdlib cimport malloc, free
from libcpp.queue cimport priority_queue
from libcpp.vector cimport vector
def testPriorityQueue():
cdef myType * item
cdef priority_queue[myType*] q
item = <myType *> malloc(sizeof(myType))
item.key = 20
item.a = 3.
item.b = 4.
q.push(item)
item = <myType *> malloc(sizeof(myType))
item.key = 10
item.a = 1.
item.b = 2.
q.push(item)
item = q.top()
print('q.top',item.key,item.a,item.b)
现在无论是编译器还是运行时都没有提供任何错误信息,当然优先级_queue中的排序无法定义,从打印结果中我得到的是最上面的项目是最后推送的。
在C++中,为了使priority_queue在这种情况下对被推送的项目进行排序,应该提供一个比较方法作为队列实例化的参数,但据我发现,这应该通过少操作符的重载来实现,就像这个C++例子一样。
struct ToastCompare
{
bool operator()(const Toast &t1, const Toast &t2) const
{
int t1value = t1.bread * 1000 + t1.butter;
int t2value = t2.bread * 1000 + t2.butter;
return t1value < t2value;
}
};
我试着在cython中定义一个类似的函数,在pyx文件中加入以下几行。
simple.pyx
cdef extern from *:
"""
struct itemCompare{
bool operator() (self, myType *t1, myType *t2) const
{
return t1.key < t2.key;
}
};
"""
ctypedef struct itemCompare
cdef priority_queue[myType*,vector[myType*],itemCompare] q
但在编译过程中,我得到一个 "priority_queue templated type接收1个参数,得到3个" 错误。
在cython中是否可以使用C++的priority_queue容器与自定义类对象?
simple.pyx
cdef extern from *:
"""
bool operator<(const myType t1, const myType t2)
{ return t1.key < t2.key;}
"""
def testPriorityQueue():
cdef priority_queue[myType*] q
离去 简单.pxd
cimport cython
from libcpp cimport bool
ctypedef struct myType:
int key
float a
float b
但它无法编译,给出了
simple.cpp:694:26: error: 'myType' does not name a type bool operator<(const myType t1, const myType t2)
所以我试着把C-verbatim代码中的struct定义移到了C-verbatim代码中,并把它从 简单.pxd
simple.pyx
def extern from *:
"""
typedef struct myType{
int key;
float a;
float b;
} myType;
bool operator<(const myType t1, const myType t2)
{return t1.key < t2.key;}
"""
ctypedef struct myType
def testPriorityQueue():
cdef myType * item
cdef priority_queue[myType*] q
item = <myType *> malloc(sizeof(myType))
现在的编译错误是
Cannot take sizeof incomplete type 'myType'(不能接受不完整类型'myType')
如果我把结构定义也留在pxd文件中,但去除了 ctypedef struct myType 从 pyx 中没有发生编译错误,但优先级队列没有排序,好像没有超载一样。
我的错误在哪里?
我的问题的答案是使用以下的方法 pxd 文件。
cimport cython
from libcpp cimport bool
cdef extern from *:
"""
typedef struct {
int key;
float a;
float b;
} myType;
bool operator<(const myType t1, const myType t2) {
return t1.key < t2.key;
}
"""
ctypedef struct myType:
int key
float a
float b
感谢 @ead 的帮助