3

double 配列と整数配列を入力する SWIG を使用して、C++ 関数を Python に渡したいと思います。これを行う方法はありますか?

たとえば、double 配列と int 配列を受け取る C++ 関数があります。

double myfun(double* a, int n, int* b, int m){...}

書いてみたSWIGインターフェースファイルに

%apply (double* IN_ARRAY1, int DIM1, int* IN_ARRAY1, int DIM1) {(double* a, int n, int* b, int m)}

しかし運がない。コンパイルはできましたが、python のように myfun 関数を呼び出すことができませんでした

myfun(a,b) 

ここで、a は double numpy 配列、b は整数 numpy 配列です。Python で次のエラーが発生します。

myfun() takes exactly 4 arguments (2 given)

助言がありますか?これは可能ですか?

ありがとう!

4

1 に答える 1

1

簡単な答えは、2 つの入力を受け取るが、numinputs 属性が 1 に設定されている typemap を使用する必要があるということです。

%module test

%typemap(in,numinputs=1) (double *a, size_t) %{
  assert(PyList_Check($input));
  $2 = PyList_Size($input);
  $1 = malloc(sizeof *$1 * $2);
  for(size_t i = 0; i < $2; ++i) {
    $1[i] = PyFloat_AsDouble(PyList_GetItem($input, i));
  }
%}

%typemap(in, numinputs=1) (int *b, size_t) %{
  assert(PyList_Check($input));
  $2 = PyList_Size($input);
  $1 = malloc(sizeof *$1 * $2);
  for (size_t i = 0; i < $2; ++i) {
    $1[i] = PyInt_AsLong(PyList_GetItem($input, i));
  }
%}

%typemap(freearg) (double *a, size_t) %{
  free($1);
%}

%typemap(freearg) (int *b, size_t) %{
  free($1);
%}

%inline %{
  double myfun(double *a, size_t n, int *b, size_t m) {
    (void)a; (void) b;
    printf("%d, %d\n", n, m);
    for (size_t i = 0; i < (n > m ? n : m); ++i) {
      printf("%d: %f - %d\n", i, i < n ? a[i] : 0, i < m ? b[i] : 0);
    }
    return 1.0;
  }
%}

これは機能し、(array, len) の各ペアのタイプマップがあり、次のように使用するのに十分です:

import test

a = [0.5, 1.0, 1.5]
b = [1,2,3]

test.myfun(a,b)

allocaまたは C99 の VLA 機能を使用して、malloc呼び出しの必要性を回避することもできましたが、説明のためにこれが機能します。

(注:関数プロトタイプのどこにも書いていませんconstが、それは入力配列を変更していないことを意味します。そうでない場合は、対応する argout typemap を記述して、割り当てられた配列からコピーする必要があります。 Python リストに追加されます)。

ただし、これは非常に反復的であるため、2 つの間でコードを共有できればより良いかもしれません。必要に応じて、より高度な SWIG 機能を使用して共有できます。必要に応じて、リストだけでなく、入力としてメモリ ビューのサポートを追加することもできます。

于 2013-07-14T14:19:37.290 に答える