本文介绍了用ctypes传递数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个C函数

void read_FIFO_AI0(int16_t** input, size_t size, NiFpga_Session* session, NiFpga_Status* status)
{
  *input = (int16_t*) malloc (size*sizeof(int16_t));
  // function that populates the array *input
}

填充数组"* input".现在,我想将该数组中的数据传递给python进行进一步处理.我尝试使用ctypes来做到这一点:

which populates the array "*input". Now I want to pass the data in that array to python for further processing. I try to use ctypes to do that:

def read_FIFO_AI0(size,session,status):
    _libfpga.read_FIFO_AI0.argtypes = [POINTER(ARRAY(c_int16, size)), c_int, POINTER(c_uint32), POINTER(c_int32)]
    _libfpga.read_FIFO_AI0.restype = None

    values = (c_int16*size)()
    _libfpga.read_FIFO_AI0(byref(values),size,byref(session),byref(status))
    return values

代码执行了,但是在数组中得到了错误的结果.当我尝试从C中使用C函数时,会得到正确的结果:

The code executes but I get wrong results in the array. When I try to use the C function from within C I get proper results:

size_t size=20;
int16_t* input;

read_FIFO_AI0(&input, size, &session, &status);

什么是填充数组的正确方法,以便我可以用Python访问数据?我不限于使用指向要填充的数组的指针,也可以在C函数中创建该数组并将其作为返回值发送给Python,但我也没有用.

What would be the right way to populate the array such that I can access the data in Python? I'm not tied to using a pointer to an array that gets populated, I would also be fine with creating the array in the C function and sending this as a return to Python, but I did not get to work either.

推荐答案

第一个参数的类型为POINTER(POINTER(c_int16))而不是POINTER(ARRAY(c_int16,size)).

The first argument's type is POINTER(POINTER(c_int16)) not POINTER(ARRAY(c_int16,size)).

这是一个简短的例子:

#include <stdlib.h>
#include <stdint.h>
__declspec(dllexport) void read(int16_t** input, size_t size)
{
  int i;
  int16_t* p = (int16_t*) malloc (size*sizeof(int16_t));
  for(i=0;i<size;i++)
    p[i] = i;
  *input = p;
}
__declspec(dllexport) void release(int16_t* input)
{
    free(input);
}

x.py

from ctypes import *
x = CDLL('x')
x.read.argtypes = POINTER(POINTER(c_int16)),c_size_t
x.read.restype = None
x.release.argtypes = [POINTER(c_int16)]
x.release.restype = None
p = POINTER(c_int16)()
x.read(p,5)
for i in range(5):
    print(p[i])
x.release(p)

输出:

0
1
2
3
4

请注意,如果您不记得free malloc的话,这可能会导致内存泄漏.更好的方法是在Python中分配缓冲区并告诉C函数大小:

Note this leaves you with potential memory leak if you don't remember to free the malloc. A better way would be to allocate the buffer in Python and tell the C function the size:

#include <stdlib.h>
#include <stdint.h>
__declspec(dllexport) void read(int16_t* input, size_t size)
{
  int i;
  for(i=0;i<size;i++)
    input[i] = i;
}

x.py

from ctypes import *
x = CDLL('x')
x.read.argtypes = POINTER(c_int16),c_size_t
x.read.restype = None
p = (c_int16*5)()
x.read(p,len(p))
print(list(p))

输出

[0, 1, 2, 3, 4]

这篇关于用ctypes传递数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-25 06:13