如何将 Numpy 数组传递给 cffi 函数以及如何将其取出? [英] How to pass a Numpy array into a cffi function and how to get one back out?

查看:58
本文介绍了如何将 Numpy 数组传递给 cffi 函数以及如何将其取出?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Python 和 Numpy 开发音频算法.现在我想通过在 C 中实现它的一部分来加速该算法.过去,我已经使用 cython 完成此操作.现在我想使用新的 cffi 做同样的事情.

I am developing an audio algorithm using Python and Numpy. Now I want to speed up that algorithm by implementing a part of it in C. In the past, I have done this using cython. Now I want to do the same thing using the new cffi.

出于测试目的,我编写了一个简单的 C 函数:

For testing purposes, I wrote a trivial C function:

void copy(float *in, float *out, int len) {
    for (int i=0; i<len; i++) {
        out[i] = in[i];
    }
}

现在我想创建两个 numpy 数组并让它们由这个函数处理.我想出了一种方法来做到这一点:

Now I want to create two numpy arrays and have those be processed by this function. I figured out a way to do that:

import numpy as np
from cffi import FFI

ffi = FFI()
ffi.cdef("void copy(float *in, float *out, int len);")
C = ffi.dlopen("/path/to/copy.dll")

float_in = ffi.new("float[16]")
float_out = ffi.new("float[16]")

arr_in = 42*np.ones(16, dtype=np.float32)

float_in[0:16] = arr_in[0:16]
C.copy(float_in, float_out, 16)
arr_out = np.frombuffer(ffi.buffer(float_out, 16*4), dtype=np.float32)

但是,我想改进这段代码:

However, I would like to improve this code:

  1. 有没有办法直接访问 numpy 数组的底层浮点缓冲区而不复制它们?
  2. ffi.buffer 非常方便将 C 数组的内容快速转换为 Numpy 数组.有没有一种等效的方法可以在不复制单个元素的情况下将 numpy 数组快速转换为 C 数组?
  3. 对于某些应用程序,float_in[0:16] = arr_in[0:16] 是一种访问数据的便捷方式.相反, arr_out[0:16] = float_out[0:16] 但是不起作用.为什么不呢?
  1. Is there a way to directly access the underlying float buffers of the numpy arrays without copying them?
  2. ffi.buffer is very convenient for quickly converting to contents of a C array to a Numpy array. Is there an equivalent way for quickly converting a numpy array into a C array without copying the individual elements?
  3. For some applications, float_in[0:16] = arr_in[0:16] is a convenient way of accessing data. The opposite, arr_out[0:16] = float_out[0:16] does not work however. Why not?

推荐答案

ndarray的ctypes属性可以和ctypes模块交互,例如ndarray.ctypes.data 是数组的数据地址,可以将其强制转换为 float * 指针,然后将指针传递给 C 函数.

The ctypes attribute of ndarray can interact with the ctypes module, for example, ndarray.ctypes.data is the data address of the array, you can cast it to a float * pointer, and then pass the pointer to the C function.

import numpy as np
from cffi import FFI

ffi = FFI()
ffi.cdef("void copy(float *in, float *out, int len);")
C = ffi.dlopen("ccode.dll")

a = 42*np.ones(16, dtype=np.float32)
b = np.zeros_like(a)
pa = ffi.cast("float *", a.ctypes.data)
pb = ffi.cast("float *", b.ctypes.data)

C.copy(pa, pb, len(a))
print b

对于您的问题 3:

我认为 ffi 数组没有为 numpy 提供访问其内部缓冲区的必要信息.因此 numpy 尝试将其转换为失败的浮点数.

I think ffi array doesn't provide numpy the necessary information to access it's inner buffer. So numpy try to convert it to a float number which failed.

我能想到的最佳解决方案是先将其转换为列表:

The best solution I can thinks is convert it to list first:

float_in[0:16] = list(arr_in[0:16])

这篇关于如何将 Numpy 数组传递给 cffi 函数以及如何将其取出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆