将Numpy数组传递给C函数进行input和输出

哦,我的话我是一个傻瓜。 调用该函数时,我简单地省略了第二个和第三个参数。 像一个傻瓜。 因为这就是我。 原来愚蠢的问题如下:

这似乎是一个非常普通的事情,但是我找不到相关的教程,对于Numpyctypes我自己也搞不清楚。

我在文件ctest.c有一个C函数。

 #include <stdio.h> void cfun(const void * indatav, int rowcount, int colcount, void * outdatav) { //void cfun(const double * indata, int rowcount, int colcount, double * outdata) { const double * indata = (double *) indatav; double * outdata = (double *) outdatav; int i; puts("Here we go!"); for (i = 0; i < rowcount * colcount; ++i) { outdata[i] = indata[i] * 2; } puts("Done!"); } 

(正如你所猜测的,我最初的论点是double *而不是void *,但是不知道在Python方面做什么,我一定会喜欢把它们改回来,但是我并不挑剔只要它工作。)

我做了一个共享库。 gcc -fPIC -shared -o ctest.so ctest.c

然后在Python中,我有一些numpy数组,我想将它们传递给C函数,一个作为input,一个作为输出。

 indata = numpy.ones((5,6), dtype=numpy.double) outdata = numpy.zeros((5,6), dtype=numpy.double) lib = ctypes.cdll.LoadLibrary('./ctest.so') fun = lib.cfun # Here comes the fool part. fun(ctypes.c_void_p(indata.ctypes.data), ctypes.c_void_p(outdata.ctypes.data)) print 'indata: %s' % indata print 'outdata: %s' % outdata 

这不报告任何错误,但打印出来

 >>> Here we go! Done! indata: [[ 1. 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1. 1.]] outdata: [[ 0. 0. 0. 0. 0. 0.] [ 0. 0. 0. 0. 0. 0.] [ 0. 0. 0. 0. 0. 0.] [ 0. 0. 0. 0. 0. 0.] [ 0. 0. 0. 0. 0. 0.]] 

outdata数组未被修改。 事实上,如果我再次调用函数,我会得到一个段错误。 这并不令我感到惊讶 – 我真的不知道我在这里做什么。 任何人都可以指向正确的方向吗?

只需将所有四个parameter passing给C函数。 改变你的Python代码:

 fun(ctypes.c_void_p(indata.ctypes.data), ctypes.c_void_p(outdata.ctypes.data)) 

至:

 fun(ctypes.c_void_p(indata.ctypes.data), ctypes.c_int(5), ctypes.c_int(6), ctypes.c_void_p(outdata.ctypes.data)) 

虽然不是你原来的问题的直接答案,这是一个更方便的方式来调用你的function。 首先,制作C函数的原型,就像在C中一样。因为你不需要分别计算rowcountcolcount ,所以我将它们合并成一个单一的size参数:

 void cfun(const double *indatav, size_t size, double *outdatav) { size_t i; for (i = 0; i < size; ++i) outdatav[i] = indatav[i] * 2.0; } 

现在以下面的方式定义ctypes原型:

 from numpy.ctypeslib import ndpointer lib = ctypes.cdll.LoadLibrary("./ctest.so") fun = lib.cfun fun.restype = None fun.argtypes = [ndpointer(ctypes.c_double, flags="C_CONTIGUOUS"), ctypes.c_size_t, ndpointer(ctypes.c_double, flags="C_CONTIGUOUS")] 

现在,调用你的函数将非常方便:

 indata = numpy.ones((5,6)) outdata = numpy.empty((5,6)) fun(indata, indata.size, outdata) 

你也可以定义一个包装器,使其更加方便:

 def wrap_fun(indata, outdata): assert indata.size == outdata.size fun(indata, indata.size, outdata)