2012-11-18 39 views
3

最近我正在做一個項目,一個函數被大量調用,所以我想在這部分中使用C代碼。我是ctypes的新手,如果我的問題很簡單,請原諒我。我怎樣才能將一個「整數指針數組」傳遞給c庫中的一個函數?python

這裏我有一個Python 2D名單:

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

我想調用C模塊中的功能與它的參數。由於C中沒有2d列表,我想將它轉換爲* 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」錯誤。

那麼,請告訴我如何使它工作?非常感謝你。

回答

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庫函數。

+0

驚人溶液。非常感謝。 –

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)) 
+0

這個問題非常好。非常感謝你。 –

+0

其實非常感謝你的鼓舞人心的回答。我曾經用for循環(請原諒我的業餘c級)用len(L)次malloc編寫我的c代碼,當我用一個指向偏移量的指針數組將它修改爲1d數組後,速度實際上顯着增加,這給了我一個演講,不要在循環中使用malloc :-) –

相關問題