4

最近、関数が頻繁に呼び出されるプロジェクトを行っているので、この部分ではCコードを使用したいと思います。私はctypesの初心者です。質問が非常に簡単な場合は、ご容赦ください。

ここに私はPythonの2Dリストを持っています:

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

パラメータとしてCモジュールの関数を呼び出したい。CIには2d-listがないので、それを*intの配列に変換したいと思います。

エントリの長さがそれぞれ異なるため、通常の2DC配列は必要ありません。

私が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, 1, 2, 1, 2, 3]

そして、次のようなすべてのサブリストの開始を表す別のリストを渡します。

[0, 1, 3, 6]

したがって、最初のサブリストは0で始まり、1で終わり、2番目のサブリストは1で始まり、3で終わり、3番目のサブリストは3で始まり、6で終わります。

この2つのリストをint配列に変換し、2番目の配列の長さで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 に答える