使用 CFFI 在 Python 中创建 CData 类型的缓冲区

Posted

技术标签:

【中文标题】使用 CFFI 在 Python 中创建 CData 类型的缓冲区【英文标题】:Create a CData-typed buffer in Python with CFFI 【发布时间】:2016-09-10 03:28:00 【问题描述】:

我正在尝试在 Python 中创建一个特殊类型的缓冲区,以将其发送到用 CFFI 包装的 C 函数。

在 C 中,我有类似的东西:

typedef unsigned char UINT8;
typedef UINT8* PUINT8;

然后,在 Python 中,以上行在 ffi.cdef() 中,我的缓冲区实例化代码如下所示:

nb_buffer = 8
buffer_size = 42

buffers = ffi.new( "PUINT8[]", nb_buffer )

for i in range( nb_buffer ):
    tmp_buffer = ffi.buffer( ffi.new( "UINT8[]", 1 ), buffer_size )
    buffers[ i ] = ffi.cast( "PUINT8", ffi.from_buffer( tmp_buffer ) )

c.function( buffers )

C 函数接收一个 UINT8**。

并且...在 C 函数中以更远的分段错误结束。

所以我在使用ffi.castprint buffers[ i ]

<cdata 'unsigned char *' 0x2cbaca0>
<cdata 'unsigned char *' 0x2cbacd8>
<cdata 'unsigned char *' 0x2cbaca0>
<cdata 'unsigned char *' 0x2cbacd8>
<cdata 'unsigned char *' 0x2cbaca0>
<cdata 'unsigned char *' 0x2cbacd8>
<cdata 'unsigned char *' 0x2cbaca0>
<cdata 'unsigned char *' 0x2cbacd8>

我错过了什么?缓冲区是否在覆盖tmp_buffer 后立即被垃圾回收?

【问题讨论】:

不看细节,但ffi.buffer( ffi.new( "UINT8[]", 1 ), ... )基本是错的。它的意思是“分配一个数组(一个 UINT8 的);然后为它取一个缓冲区;然后立即忘记新数组,以便立即释放它”。 另外,您分配一个 UINT8 的数组,然后将它们视为 42 字节缓冲区。最后 41 个字节无论如何都没有分配。 我认为ffi.buffer() 的第一个参数的重要性是 CData 的类型,而不是它的长度(因为它是第二个参数)并且它会以某种方式创建一个给定的 CData 类型给定大小的缓冲区。但我现在明白,第二个参数用于分割比需要更大的内存大小。谢谢阿明!我会尽快尝试你的答案。 ffi.buffer() 没有分配任何内存,它只是返回现有内存的视图。 【参考方案1】:

使用列表推导:

keepalive = [ ffi.new( "UINT8[]", buffer_size ) for i in range( nb_buffer ) ]
buffers = ffi.new( "PUINT8[]", keepalive )

c.functions( buffers )

# keepalive stays alive at least until here

【讨论】:

【参考方案2】:

怎么样:

buffers = ffi.new( "PUINT8[]", nb_buffer )
keepalive = []

for i in range( nb_buffer ):
    p = ffi.new("UINT8[]", buffer_size)
    keepalive.append(p)
    buffers[i] = p

c.function( buffers )

# keepalive stays alive at least until here

【讨论】:

以上是关于使用 CFFI 在 Python 中创建 CData 类型的缓冲区的主要内容,如果未能解决你的问题,请参考以下文章

在 Python CFFI 中声明包含 time_t 字段的结构

使用带有嵌入式 PyPy 的外部“Python”样式 cffi 回调

如何使用 cffi 在 C 中嵌入一个返回字符串的 Python 函数?

如何配置 python cffi 库以使用 mingw?

为啥 cffi 比 numpy 快这么多?

在 Windows 上安装 python 库 cffi