Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 将一组NumPy数组传递到C函数以进行输入和输出_Python_C_Numpy_Ctypes_Ffi - Fatal编程技术网

Python 将一组NumPy数组传递到C函数以进行输入和输出

Python 将一组NumPy数组传递到C函数以进行输入和输出,python,c,numpy,ctypes,ffi,Python,C,Numpy,Ctypes,Ffi,假设我们有一个C函数,它接受一组或多个输入数组,处理它们,并将其输出写入一组输出数组。签名如下所示(其中count表示要处理的数组元素数): void计算(整数计数、浮点**输入、浮点**输出) 我想通过ctypes从Python调用这个函数,并使用它将转换应用于一组NumPy数组。对于定义为的单输入/单输出函数 void计算(整数计数、浮点*输入、浮点*输出) 以下工作: 导入ctypes 进口numpy 从numpy.ctypeslib导入ndpointer lib=ctypes.cdl

假设我们有一个C函数,它接受一组或多个输入数组,处理它们,并将其输出写入一组输出数组。签名如下所示(其中
count
表示要处理的数组元素数):

void计算(整数计数、浮点**输入、浮点**输出)
我想通过ctypes从Python调用这个函数,并使用它将转换应用于一组NumPy数组。对于定义为的单输入/单输出函数

void计算(整数计数、浮点*输入、浮点*输出)
以下工作:

导入ctypes
进口numpy
从numpy.ctypeslib导入ndpointer
lib=ctypes.cdll.LoadLibrary(“./block.so”)
fun=lib.compute
fun.restype=None
fun.argtypes=[ctypes.c_int,
ndpointer(ctypes.c_float),
ndpointer(ctypes.c_float)]
data=numpy.ones(1000).astype(numpy.float32)
输出=numpy.zeros(1000).astype(numpy.float32)
乐趣(1000,数据,输出)
但是,我不知道如何为多个输入(和/或输出)创建相应的指针数组。有什么想法吗

Edit:因此人们一直想知道
compute
如何知道需要多少数组指针(因为
count
指的是每个数组的元素数)。事实上,这是硬编码的;给定的
计算
准确地知道预期的输入和输出数量。调用方的任务是验证
输入
输出
是否指向正确的输入和输出数量。下面是一个示例
compute
获取2个输入并写入1个输出数组:

virtual void compute (int count, float** input, float** output) {
    float* input0 = input[0];
    float* input1 = input[1];
    float* output0 = output[0];
    for (int i=0; i<count; i++) {
        float fTemp0 = (float)input1[i];
        fRec0[0] = ((0.09090909090909091f * fTemp0) + (0.9090909090909091f * fRec0[1]));
        float fTemp1 = (float)input0[i];
        fRec1[0] = ((0.09090909090909091f * fTemp1) + (0.9090909090909091f * fRec1[1]));
        output0[i] = (float)((fTemp0 * fRec1[0]) - (fTemp1 * fRec0[0]));
        // post processing
        fRec1[1] = fRec1[0];
        fRec0[1] = fRec0[0];
    }
}
virtualvoid计算(整数计数、浮点**输入、浮点**输出){
float*input0=输入[0];
float*input1=输入[1];
float*output0=输出[0];

对于C中的(int i=0;i,
float**
指向
float*
指针的表/数组中的第一个元素

大概每个
float*
都指向
float
值的表/数组中的第一个元素

您的函数声明有1个计数,但不清楚此计数适用于什么:

void compute (int count, float** input, float** output)
  • 2D矩阵
    count
    x
    count
    大小
  • count
    -大小为
    浮点*的数组
    以某种方式终止,例如使用
    nan
  • 以null结尾的
    float*
    每个
    count
    元素数组(合理假设)
请澄清您的问题,我将澄清我的答案:-)

假设最后一个API解释,下面是我的示例计算函数:

/* null-terminated array of float*, each points to count-sized array
*/
extern void compute(int count, float** in, float** out)
{
    while (*in)
    {
        for (int i=0; i<count; i++)
        {
            (*out)[i] = (*in)[i]*42;
        }
        in++; out++;
    }
}
#include <stdio.h>
extern void compute(int count, float** in, float** out);

int main(int argc, char** argv)
{
#define COUNT 3
    float ina[COUNT] = { 1.5, 0.5, 3.0 };
    float inb[COUNT] = { 0.1, -0.2, -10.0 };
    float outa[COUNT];
    float outb[COUNT];
    float* in[] = {ina, inb, (float*)0};
    float* out[] = {outa, outb, (float*)0};

    compute(COUNT, in, out);

    for (int row=0; row<2; row++)
        for (int c=0; c<COUNT; c++)
            printf("%d %d %f %f\n", row, c, in[row][c], out[row][c]);
    return 0;
}
这里介绍了ctypes的Numpy接口,arr.ctypes.shape[:]arr.ctypes.strips[:]和arr.ctypes.data是您所需要的;您可以直接将其提供给
计算

下面是一个例子:

In [55]: a = numpy.array([[0.0]*10]*2, dtype=numpy.float32)

In [56]: ctypes.cast(a.ctypes.data, ctypes.POINTER(ctypes.c_float))[0]
Out[56]: 0.0

In [57]: ctypes.cast(a.ctypes.data, ctypes.POINTER(ctypes.c_float))[0] = 1234

In [58]: a
Out[58]: 
array([[ 1234.,     0.,     0.,     0.,     0.,     0.,     0.,     0.,
            0.,     0.],
       [    0.,     0.,     0.,     0.,     0.,     0.,     0.,     0.,
            0.,     0.]], dtype=float32)

要特别针对Numpy阵列执行此操作,可以使用:

import numpy as np
import ctypes

count = 5
size = 1000

#create some arrays
arrays = [np.arange(size,dtype="float32") for ii in range(count)] 

#get ctypes handles
ctypes_arrays = [np.ctypeslib.as_ctypes(array) for array in arrays]

#Pack into pointer array
pointer_ar = (ctypes.POINTER(C.c_float) * count)(*ctypes_arrays)

ctypes.CDLL("./libfoo.so").foo(ctypes.c_int(count), pointer_ar, ctypes.c_int(size))
事情的C面可能是这样的:

# function to multiply all arrays by 2
void foo(int count, float** array, int size)
{
   int ii,jj;
   for (ii=0;ii<count;ii++){
      for (jj=0;jj<size;jj++)
         array[ii][jj] *= 2;    
   }

}
#将所有数组乘以2的函数
void foo(整数计数、浮点**数组、整数大小)
{
int ii,jj;

对于(ii=0;ii确实有帮助吗?不幸的是,没有。它更具体地针对NumPy和ctypes。不过,谢谢你。可能你需要重写
compute
来存储数据平面。
compute
函数是自动生成的,所以我对签名和实现的影响很小。你怎么知道在自动生成中ed函数,插入了多少个数组?这看起来很好。您的解释当然非常正确:
count
指的是
float*
“数组”中的元素数。
float**
包含的指针数在
compute
的生成时已知,因此
compute
知道需要多少输入和输出。(它是通过编译另一种语言生成的。)因此,不需要空终止。我将修改这个问题。ebarr的具体提示起到了作用;尽管如此,非常感谢您的深入解释,帮助澄清了这个问题,并教会了我很多关于接口的知识。。。
# function to multiply all arrays by 2
void foo(int count, float** array, int size)
{
   int ii,jj;
   for (ii=0;ii<count;ii++){
      for (jj=0;jj<size;jj++)
         array[ii][jj] *= 2;    
   }

}