最近我正在做一个大量调用函数的项目,所以我想在这部分中使用C代码。我是ctypes的新手,如果我的问题非常简单,请原谅我。
这里我在python中有一个2d列表:
L = [[1],[1,2],[1,2,3]]
我想在C模块中调用一个函数,并将其作为参数。由于C中没有2d-list,我想将其转换为* int的数组。
我不想要普通的2D C数组,因为每个条目的长度都不同。
我在python部分做的是:
L = [[1],[1,2],[1,2,3]]
entrylist = []
for entry in L:
c_entry = (ctypes.c_int * len(entry))(*entry) # c_entry is the C array version of entry
entrylist.append(c_entry)
c_L = (ctypes.POINTER(ctypes.c_int) * len(entrylist))(*entrylist) # create an array of integer pointer, then initial it
当c_L
时, len(L) == 14
是“LP_c_long_Array_14对象”。
另外,我可以使用
完美地打印出来for i in range(len(L)):
for j in range(len(L[i])):
print(L[i][j], end = ' ')
print()
另一方面,在C代码中,我将我的函数定义为:
int fun(int** c_L)
int fun( (int * c_L)[])
既不起作用。 ctypes抛出“不知道如何转换参数1”错误。
那么,请告诉我如何使它工作?非常感谢你。
答案 0 :(得分:3)
你几乎就在那里,你只需要一些调整。
import ctypes as C
lib = C.CDLL("libfoo.so")
l = [[1],[1,2],[1,2,3]]
entrylist = []
lengths = []
for sub_l in l:
entrylist.append((C.c_int*len(sub_l))(*sub_l))
lengths.append(C.c_int(len(sub_l)))
c_l = (C.POINTER(C.c_int) * len(entrylist))(*entrylist)
c_lengths = ( C.c_int * len(l))(*lengths)
lib.test(c_l, c_lengths, len(l)) #here we also pass the sizes of all the arrays
事物的C面看起来像:
#include <stdlib.h>
#include <stdio.h>
int test(int **ar,int *lens,int n_ar){
int ii,jj,kk;
for (ii=0;ii<n_ar;ii++){
for (jj=0;jj<lens[ii];jj++){
printf("%d\t",ar[ii][jj]);
}
printf("\n");
fflush(stdout);
}
return 0;
}
如果这不起作用,那么将所有参数显式地转换为c库函数可能会有用。
答案 1 :(得分:0)
我认为您可以通过将所有数据打包到一个列表中来避免int**
指针:
[1, 1, 2, 1, 2, 3]
并传递另一个表示每个子列表开头的列表,例如:
[0, 1, 3, 6]
所以第一个子列表从0开始,从1开始,第二个子列表从1开始,到3结束,第三个子列表从3开始,结束于6。
将这两个列表转换为int数组,并将其传递给具有第二个数组长度的c函数。
以下是一个例子:
#include <stdio.h>
void sum_list(int * data, int * positions, int length)
{
int i, j, s;
for(i=0;i<length-1;i++)
{
s = 0;
for(j=positions[i];j<positions[i+1];j++)
{
s += data[j];
}
printf("%d\n", s);
}
}
和python代码:
L = [[1],[1,2],[1,2,3]]
data = []
positions = [0]
for sub in L:
data.extend(sub)
positions.append(len(data))
from ctypes import *
lib = CDLL("./sum_list.out")
c_data = (c_int * len(data))(*data)
c_positions = (c_int * len(positions))(*positions)
lib.sum_list(c_data, c_positions, len(c_positions))