8

構造体で関数ポインターを使用してメンバー関数を実装し、構造体へのポインターを各関数の最初の引数として渡します。 C++.

%module mytest
%{
typedef struct mytest mytest;

struct mytest {
  int data;
  int (*func1)(mytest *,int);
  void (*func2)(mytest *,int);
};

int f1(mytest *me,int n) { return me->data + n; }
void f2(mytest *me,int n) { me->data += n; }

mytest *mytestNew(int n) {
  mytest *me = (mytest*) malloc(sizeof(mytest));
  me->data = n;
  me->func1 = f1;
  me->func2 = f2;
  return me;
}

%}

typedef struct mytest mytest;

struct mytest {
  int data;
  int func1(mytest *,int);
  void func2(mytest *,int);
};

extern mytest *mytestNew(int n);

今私の問題は、インターフェイスがフロントエンドで選択した言語に作成されると、言語自体が this の非表示をサポートしているにもかかわらず、明示的に「this」ポインターをオブジェクトに渡さなければならなくなることです。

たとえば、Python を選択したとします。私はこのようなことをしなければなりません:

from mytest import *
m = mytestNew(1)
m.func1(m,0)

私が本当に欲しいのは、次のようにすることです:

from mytest import *
m = mytestNew(1)
m.func1(0)

ラッピング コードを書くことができることはわかっていますが、実際のプロジェクトでは、既存の C コードの多くのオブジェクトに多くの関数があり、これをサポートしたいすべての言語で掛け合わせると、あまりにも多くの作業になります! SWIGにこれを自動的に行わせる方法はありますか?

4

1 に答える 1

4

タイプマップを選択的に適用できるようにするための定義と同様に、SWIG インターフェイスで一貫性のある名前をパラメータに付ければ、2 つのタイプマップだけを使用して、SWIG で言語中立的な方法でこれを行うことができます。mytest(もちろん、デフォルトですべてのポインタを「this」ポインタにしたい場合を除きます)

必要なタイプマップは次のとおりです。

// Make sure the wraqpped function doesn't expect an input for this:
%typemap(in,numinputs=0) mytest *me "$1=NULL;"
// Slightly abuse check typemap, but it needs to happen after the rest of the arguments have been set:
%typemap(check) mytest *me {
  $1 = arg1;
}

check typemap は実際にはこのような使用を意図したものではありませんが、引数がターゲット言語から抽出された後、実際の呼び出しが行われる前にコードを挿入する最も簡単な方法です。

マクロを使用してモジュールを単純化し、関数ポインターとメンバー トリックの間のマッピングを記述して同期を維持する必要がないようにすることもできます。私は次のようになりtest.hました:

#ifdef SWIG
#define MEMBER(name, args) name args
#else
#define MEMBER(name, args) (*name) args
#endif

typedef struct mytest mytest;

struct mytest {
  int data;
  int  MEMBER(func1,(mytest *me,int));
  void MEMBER(func2,(mytest *me,int));
};

対応するインターフェイス ファイル (test.i):

%module test

%{
#include "test.h"

static int f1(mytest *me,int n) { return me->data + n; }
static void f2(mytest *me,int n) { me->data += n; }
%}

%extend mytest {
  mytest(int n) {
    $self->data = n;
    $self->func1 = f1;
    $self->func2 = f2;
  }
}

%typemap(in,numinputs=0) mytest *me "$1=NULL;"
%typemap(check) mytest *me {
  $1 = arg1;
}

%include "test.h"

(このインターフェース ファイルは、Java プログラマーが期待するとおりに「オブジェクト」を「作成」するコンストラクターを提供します。呼び出しnewて、関数ポインターを舞台裏で設定することができます)

于 2012-06-14T08:58:14.047 に答える