4

最近我正在做一个函数被大量调用的项目,所以我想在这部分使用 C 代码。我是ctypes的新手,如果我的问题很简单,请原谅我。

在这里,我在 python 中有一个二维列表:

L = [[1],[1,2],[1,2,3]]

我想在 C 模块中调用一个函数,并将其作为参数。由于 CI 中没有二维列表,因此希望将其转换为 *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是一个“LP_c_long_Array_14 对象”,当len(L) == 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”错误。

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

4

2 回答 2

4

你快到了,你只需要一些调整。

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 库函数可能很有用。

于 2012-11-18T01:39:03.140 回答
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))
于 2012-11-18T03:01:54.843 回答