【问题标题】:Buffer protocol using CFFI使用 CFFI 的缓冲协议
【发布时间】:2015-12-27 11:00:09
【问题描述】:

我想公开对象的缓冲区协议,就像 Cython 文档的 in this example 一样,但是我需要使用 CFFI 来执行此操作,但我找不到任何示例来公开缓冲区协议。

【问题讨论】:

  • 我认为这没有意义。实现缓冲协议最终涉及writing some C functions yourselfadding them to a type defined using the Python C-API。 (顺便说一句,Cython 提供了一种从“类似 Python 的代码”中执行此操作的方法。CFFI 是一种从 Python 调用现有 C 库的方法,但不是编写新的 C 代码的方法。
  • 不完全是,请参阅这些docs 中的set_source 方法。它们还提供了一个ffi.buffer() 方法来返回缓冲区对象,但是这些对象不公开缓冲区协议。
  • 啊——够公平的。我的错误(我认为)。快速浏览 cffi (bitbucket.org/cffi/cffi/src/…) 的源代码表明缓冲区应该公开 Python 缓冲区协议。我不太确定我是否完全理解您的问题,但我会稍微戳一下......
  • 你是对的,cffi缓冲区已经暴露了缓冲区协议,谢谢你的帮助。请将此添加为此问题的答案,然后我可以接受它作为答案。

标签: python c cython python-cffi


【解决方案1】:

我对这个问题的理解是,您有一些从 CFFI 接口获得的数据,并希望使用标准 Python 缓冲区协议(许多 C 扩展使用该协议来快速访问数组数据)公开它。

好消息ffi.buffer() 命令(公平地说,直到 OP 提到它,我才知道它!)公开了 Python 接口和 C-API 端缓冲区协议。不过,它仅限于将数据视为无符号字符/字节数组。幸运的是,使用其他 Python 对象(例如 memoryview 可以将其视为其他类型)。

帖子的其余部分是一个说明性示例:

# buf_test.pyx
# This is just using Cython to define a couple of functions that expect
# objects with the buffer protocol of different types, as an easy way
# to prove it works. Cython isn't needed to use ffi.buffer()!
def test_uchar(unsigned char[:] contents):
    print(contents.shape[0])
    for i in range(contents.shape[0]):
        contents[i]=b'a'

def test_double(double[:] contents):
    print(contents.shape[0])
    for i in range(contents.shape[0]):
        contents[i]=1.0

...以及使用 cffi 的 Python 文件

import cffi
ffi = cffi.FFI()

data = ffi.buffer(ffi.new("double[20]")) # allocate some space to store data
         # alternatively, this could have been returned by a function wrapped
         # using ffi

# now use the Cython file to test the buffer interface
import pyximport; pyximport.install()
import buf_test

# next line DOESN'T WORK - complains about the data type of the buffer
# buf_test.test_double(obj.data) 

buf_test.test_uchar(obj.data) # works fine - but interprets as unsigned char

# we can also use casts and the Python
# standard memoryview object to get it as a double array
buf_test.test_double(memoryview(obj.data).cast('d'))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-19
    • 2011-09-18
    • 2014-01-16
    相关资源
    最近更新 更多