在cython中使用C++容器

问题描述 投票:0回答:1

我想在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容器与自定义类对象?


按照@ead的建议,我试着这样修改代码。

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 中没有发生编译错误,但优先级队列没有排序,好像没有超载一样。

我的错误在哪里?

containers cython
1个回答
0
投票

我的问题的答案是使用以下的方法 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 的帮助

© www.soinside.com 2019 - 2024. All rights reserved.