代码之家  ›  专栏  ›  技术社区  ›  Toji

从C结构创建pybuffer

  •  1
  • Toji  · 技术社区  · 15 年前

    编辑:在重新阅读我原来的问题时,我很快意识到,它的措辞很糟糕,模棱两可,而且太混乱了,无法得到一个像样的答案。这就是我在午休时间匆匆提出问题的原因。希望这会更清楚:

    我试图将一个简单的C结构作为pybuffer公开给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的现有文档非常稀疏,在某些地方是自相矛盾的,在其他地方是完全错误的(文档化的函数签名与头文件中的签名不匹配,等等),因此我不知道如何最好地公开它。另外,我希望避免包括第三方libs来实现应该是核心libs的一部分的功能,但我觉得pybuffer功能仍然相当不成熟,也许像numpy这样的功能会是更好的选择。

    有人对此有什么建议吗?

    1 回复  |  直到 14 年前
        1
  •  1
  •   Antoine P.    14 年前

    这里描述了一组要实现的方法,以便扩展类型支持缓冲区协议: 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对象。

    编辑: 更精确地说,memoryview支持某些类型的切片分配,但不支持所有类型的切片分配。此外,它们还不够“智能”,无法理解将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
    
    推荐文章