如何通过FFI传递Numpy PyArray *

时间:2016-08-31 03:10:36

标签: python numpy python-cffi

想法是能够从库中修改数组,就像从函数中“输出”一样。 例如:

var pizza = Pizza(); //undefined
var pizza = new Pizza() //your obj

1 个答案:

答案 0 :(得分:0)

您无法通过CFFI传递特定于CPython的PyXxx结构:您需要传递标准C数据。通常我会回答您需要使用标准C接口设计cdef()函数,例如:

ffi.cdef("""
    struct myimage_t {
        int width, height;
        float *data;
    };
    int read_image(struct myimage_t *output);  // fill in '*output'
    void free_image(struct myimage_t *img);   // free output->data
""")

myimage = ffi.new("struct myimage_t *")
if lib.read_image(myimage) < 0:
    raise IOError
...
lib.free_image(myimage)

然后你需要手动将myimage转换为numpy数组,在&#34; ...&#34;上面的代码。

一个更好的选择是使用Python回调:一个回调,根据规范生成numpy数组并返回一个C标准float *指针。 numpy数组本身保存在回调中的某个地方。您可以将其保存为Python全局,或者更干净地使用&#34;句柄&#34;你通过C.需要API版本,而不是ABI。在_example_build.py中:

ffi.cdef("""
   extern "Python" float *alloc_2d_numpy_array(void *handle, int w, int h);
   void read_image(void *handle);
""")
ffi.set_source("_example_cffi", """
   void read_image(void *handle)
   {
       // the C code that eventually invokes
       float *p = alloc_2d_numpy_array(handle, w, h);
        // and then fill the data at 'p'
   }
""")
ffi.compile(verbose=True)

在文件example.py中:

from _example_cffi import ffi, lib

class Context:
    pass

@ffi.def_extern()
def alloc_2d_numpy_array(handle, w, h):
    context = ffi.from_handle(handle)
    context.image = np.ndarray([w, h], dtype=np.float32)
    return ffi.cast("float *", ffi.from_buffer(context.image))

context = Context()
lib.read_image(ffi.new_handle(context))
image = context.image