如何从python中将“数组的整数指针”传递给c库中的Function

时间:2012-11-18 00:21:03

标签: python pointers 2d ctypes

最近我正在做一个大量调用函数的项目,所以我想在这部分中使用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”错误。

那么,请告诉我如何使它工作?非常感谢你。

2 个答案:

答案 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))