将C数组转换为Python字节
我正在尝试使用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 个回答
char
(字符)可以自动转换成 bytes
(字节),因为 Cython 认为它们差不多,而且转换速度很快。需要注意的是,char *
指针默认是以空字符结束的。
这种自动转换并不适用于 int *
(整数指针)。通常情况下,你会想要 转换成 Numpy 对象(这实际上是对数组的封装)。如果你想要更快的速度,可以考虑使用 cpython.array
。
看起来 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
隐藏并处理的,但它仍然是存在的。