从C结构创建PyBuffer
编辑:在重新阅读我最初的问题后,我很快意识到这个问题表述得很糟糕,含糊不清,太让人困惑,根本无法得到一个好的答案。这是我在午休结束时匆忙提问的结果。希望这次能更清楚一些:
我想把一个简单的C语言结构体暴露给Python(3.x),这样我就可以从中获取一个MemoryView。我要暴露的结构体大概是这样的:
struct ImageBuffer {
void* bytes;
int row_count;
int bytes_per_row;
};
我希望脚本编写者能够像这样访问数据:
img_buffer = img.get_buffer()
img_buffer[1::4] = 255 # Set every Red component to full intensity
不幸的是,关于这些结构体的C API的现有文档非常稀少,有些地方自相矛盾,还有些地方完全错误(文档中的函数签名和头文件中的不匹配等等)。因此,我对如何最好地暴露这个结构体并没有很好的想法。此外,我希望避免使用第三方库来实现应该是核心库的一部分的功能,但我觉得PyBuffer的功能仍然相当不成熟,也许像NumPy这样的库会是更好的选择。
有没有人对此有什么建议?
1 个回答
2
要让你的扩展类型支持缓冲区协议,需要实现一系列方法,具体内容可以在这里找到:http://docs.python.org/3.1/c-api/typeobj.html#buffer-object-structures
我知道这些文档写得比较复杂,所以我建议你可以从现有的C类型的缓冲区API实现入手,比如官方Python源代码中的bytesobject.c或bytearrayobject.c。
不过,请注意,缓冲区协议并不能让你使用一些高级的表示法,比如你提到的:img_buffer[1::4] = 255
在memoryview对象上是无法使用的。
补充:更准确地说,memoryviews支持某些类型的切片赋值,但并不是所有的。此外,它们也不够“聪明”,无法理解将255赋值给切片实际上是想让这个字节值重复。举个例子:
>>> b = bytearray(b"abcd") >>> m = memoryview(b) >>> m[0:2] = b"xy" >>> b bytearray(b'xycd') >>> m[0:2] = 255 Traceback (most recent call last): File "", line 1, in TypeError: 'int' does not support the buffer interface >>> m[0:2] = b"x" Traceback (most recent call last): File "", line 1, in ValueError: cannot modify size of memoryview object >>> m[0::2] = b"xy" Traceback (most recent call last): File "", line 1, in NotImplementedError