使用ctypes访问变量数组的内容

6 投票
1 回答
4566 浏览
提问于 2025-04-16 03:35

我在Python中使用ctypes来调用一个用C语言写的文件读取函数。因为读取的数据量很大,而且大小不确定,所以我在C语言中使用了float类型。

int read_file(const char *file,int *n_,int *m_,float **data_) {...}

这个函数会分配一个合适大小的二维数组,叫做data,这里的大小由nm决定,并把值复制到传入的引用中。下面是相关的代码片段:

*data_ = data;
*n_ = n;
*m_ = m;

我用下面的Python代码来调用这个函数:

p_data=POINTER(c_float)
n=c_int(0)
m=c_int(0)
filename='datasets/usps'
read_file(filename,byref(n),byref(m),byref(p_data))

之后,我尝试用contents来访问p_data,但我只得到了一个单独的float值。

p_data.contents
c_float(-1.0)

我的问题是:我该如何在Python中访问data

你有什么建议吗?如果我说得不清楚,请随时指出来!

1 个回答

3

用Python的struct库来做整个事情可能会更简单。不过如果你更喜欢用ctypes(我也理解,ctypes确实很酷):

#include <malloc.h>
void floatarr(int* n, float** f)
{
    int i;
    float* f2 = malloc(sizeof(float)*10);
    n[0] = 10;
    for (i=0;i<10;i++)
    { f2[i] = (i+1)/2.0; }
    f[0] = f2;
}

然后在Python中:

from ctypes import *

fd = cdll.LoadLibrary('float.dll')
fd.floatarr.argtypes = [POINTER(c_int),POINTER(POINTER(c_float))]

fpp = POINTER(c_float)()
ip = c_int(0)
fd.floatarr(pointer(ip),pointer(fpp))
print ip
print fpp[0]
print fpp[1]

这里的关键是大写的POINTER用来创建一个类型,而小写的pointer则是指向已有存储空间的指针。你可以用byref来代替pointer,他们说这样会更快。我个人更喜欢pointer,因为这样更清楚发生了什么。

撰写回答