将C数组转换为Python字节

0 投票
2 回答
1472 浏览
提问于 2025-04-18 09:41

我正在尝试使用Cython在Python3环境中运行一个C++库。
当我试图像这样把整型数组返回给Python时:

def readBytes(self, length):
    cdef int *buffer = []
    self.stream.read(buffer, length)
    return buffer 

我遇到了这个错误:

    return buffer
                ^
Cannot convert 'int *' to Python object

顺便说一下,如果我使用下面的方式,就不会出现错误:

 cdef char *buffer = ''

2 个回答

0

char(字符)可以自动转换成 bytes(字节),因为 Cython 认为它们差不多,而且转换速度很快。需要注意的是,char * 指针默认是以空字符结束的。

这种自动转换并不适用于 int *(整数指针)。通常情况下,你会想要 转换成 Numpy 对象(这实际上是对数组的封装)。如果你想要更快的速度,可以考虑使用 cpython.array

1

看起来 stream.read() 会分配一块内存给 buffer。如果是这样的话,你不能把在 C++ 中分配的内存直接返回到 Python 中。你应该:

1) 在 Python 或 Cython 代码中创建一个 Python 对象,或者如果你喜欢的话,可以创建一个 numpy 数组。

2) 把从 *buffer 指向的内存中复制的数据,放到你新创建的 Python 对象中。然后你就可以返回这个对象了。

这样做是必要的,因为 Python 不能处理在 C 空间中分配的内存,而且你在 C 代码中分配的内存会泄漏,也就是说它不会被释放。

你还问了为什么 cdef char *buffer = '' 不会报错。在这种情况下,cython 识别到 buffer 指向一个字符串,并自动生成一个新的 Python 对象,内容就是 buffer 指向的内容。下面是一个 ipython 的例子:

%%cython
def ReturnThisString():
    cdef char *buffer = 'foobar'
    return buffer

print ReturnThisString() #this outputs 'foobar'

注意,buffer 是由你的 C 编译器在栈上初始化的,使用这个函数时并不能保证字符串在那个内存位置上仍然存在。但是,当 cython 执行返回语句时,它会自动从你的 char * 指针初始化一个 Python 字符串。(在 Python 3 中,我想它会被转换成 bytes,正如 @Veedrac 所说,这只是一个小细节)。在这种情况下,Python 对象的创建和复制操作是被 cython 隐藏并处理的,但它仍然是存在的。

撰写回答