Cython - 将指针转换为数组成Python对象

11

我离完成这个任务非常接近了。在过去的几周中,我一直在尝试通过Cython创建一个Python扩展程序,以便与用C++编写的库进行交互。在这里得到一些人的帮助和几位朋友的协助下,我已经完成了大约98%的工作。唯一剩下的问题是:我无法弄清如何将指向无符号短整型数组的指针转换为Python对象(最好是列表)。

背景介绍一下,我正试图与库的一部分进行交互,它设置了一个回调函数,我已经成功地实现了这一点:

global callbackfunc

ctypedef unsigned short const_ushort "const uint16_t"

ctypedef void (*Function1)(const_ushort *data, unsigned width, unsigned height)

cdef extern from "lib.hpp":
    void SetCallback(Function1)

cdef void cSetCallback(Function1 function):
    SetCallback(function)

cdef void callcallback(const_ushort *data, unsigned width, unsigned height):
    global callbackfunc
    callbackfunc(data,width,height)

cSetCallback(callcallback)

def PySetCallback(callbackFunc):
    global callbackfunc
    callbackfunc = callbackFunc

问题出现在函数"callcallback"中,我遇到了错误:"无法将'const_ushort *'转换为Python对象"。我的第一次尝试是创建一个新的Python列表,并通过循环将数组的每个元素获取到Python列表中,就像这样:

datalist = []
for i in range(width*height):
    datalist += data[i]

不幸的是,这使我得到了编译后的Cython代码,试图将一个类型定义为"const const unsigned short",这显然是有问题的。

接着我尝试了这个方法:

datalist = []
for i in data:
    datalist += i
这给了我一个"C数组迭代需要已知的结束索引"错误。请注意,我对C/C++几乎不了解,所以大部分内容对我来说意义不大。
无论如何,有没有将这样的指针转换为Python对象的有效方法(最好比循环数组更快,因为它通常包含57344个项目,并且时间非常敏感)?
编辑: 更多说明,正如我提到的,我正在使用回调函数,并且调用此函数的库中的C++函数会发送指向“const uint_16”的数组的指针,这就是我定义const_ushort的方式,因为否则类型不统一。我无法以任何方式修改库。
编辑2: 看起来我做到了。我最终所做的是将数组显式地强制转换为无符号短整数的数组,而不是const无符号短整数的数组,以便我可以使用非常量索引它们。为了实现这一点,我创建了另一个像这样的C++函数(由别人为我编写,我几乎不懂C++):
unsigned short *convert_short(const unsigned short *test){ return const_cast<unsigned short *>(test); }

这让我能够在我的类中创建"getindex"函数,并根据该函数返回正确的值。所以Python似乎正确读取了数组等等,所以这个问题看来已经解决了。非常感谢。

2个回答

5
ctypedef unsigned short const_ushort "const uint16_t"

此代码使C代码中出现const,因此您会得到typedef unsigned short const uint16_t的结果,其中const没有意义。它还重新定义了标准类型uint16_t,这是不应该的。

您可以尝试以下代码:

ctypedef unsigned short *ushort_p "ushort_p"

由于某些原因,Cython似乎无法识别C中的const关键字。您可能需要在回调函数周围使用包装器来处理const问题。
如果您希望将指针转换为Python对象,请将其包装在cdef类中。确保该类记录高度和宽度,因为这些信息不会与C数组一起记录。

谢谢,将其包装在cdef类中似乎可以使其编译,但现在我无法弄清如何在我的Python测试脚本中访问它。 - Josiah
@Josiah:我不太清楚你如何对结构进行索引;你似乎在C代码中将其用作矩阵,在Python代码中将其用作数组。你可以尝试在cdef class中定义一个__getindex__方法,并从那里对C数组进行一维索引。 - Fred Foo

1

这不完全是你所要求的,但如果你想在Cython中使用无符号短整型数组,并使其在Python端可访问,则可以在Python端创建一个Numpy ndarray并将其传递到Cython中,在那里它与多维数组基本相同。这样,你既可以获得Python的内存管理、一些方便的索引语法,又可以在Cython中使用真实数组的速度。

这里是我的Project Euler解决方案的一个示例。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接