2012-06-13 3 views
4

구조체에서 함수 포인터를 사용하여 멤버 함수를 구현하고 암시 적 "this"와 비슷한 각 함수의 첫 번째 인수로 구조체에 대한 포인터를 전달하는 간단한 C "클래스" C++의 포인터.SWIG를 에뮬레이트 된 "this"포인터를 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); 

지금 내 문제는, 인터페이스가 나는 프런트 엔드에서 무엇을 선택 언어를 만들 때, 나는 언어 자체가 숨어 지원에도 불구하고, 명시 적으로 객체에 "이"포인터를 전달해야하는 바람입니다 이.

예를 들어 파이썬을 선택한다고 가정합니다.

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

내가 정말 원하는 것은 이런 식으로 작업을 수행하는 것입니다 :이 같은 것을 할 필요가

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

을 내가 그냥 포장 코드를 작성할 수 알고,하지만 내 실제 프로젝트 I에 대한 기존 C 코드의 많은 객체에서 많은 기능을 가지고 있으며 이것을 지원하고자하는 모든 언어로 곱하면됩니다. 이것은 너무 많은 작업입니다! SWIG가 자동으로이 작업을 수행 할 수있는 방법이 있습니까?

+1

그런데 그런 식으로 누출되면 - % newobject mytestNew'를 사용하여이를 피하려고한다. 호기심 때문에 C++을 처음 사용하지 않는 이유가 무엇입니까? – Flexo

답변

2

SWIG 인터페이스에서 매개 변수의 이름을 일관되게 지정하고 typemaps를 선택적으로 적용 할 수 있도록 정의 된 이름을 제공한다면 SWIG에서 언어 중립적 인 방식으로이 작업을 수행 할 수 있습니다. 당신이 필요로하는

적인 typemap (당신이하지 않는 한 물론 기본적으로 "이"포인터가 될 mytest에 모든 포인터를 원)이다 :

// 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; 
} 

체크 타입 맵이 정말,이 같은 사용하기위한 것이 아니라, 인수가 대상 언어에서 추출 된 후 실제 호출이 이루어지기 전에 코드를 주입하는 것이 가장 쉬운 방법입니다.

매크로를 사용하여 모듈을 단순화하여 함수 포인터와 멤버 간의 트릭 매핑을 작성하고 동기화하지 않아도됩니다.

#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.h으로 돌아가 셨습니다

%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" 

(이 인터페이스 파일은 "개체를" "생성"생성자를 제공 정확히 어떻게 자바 프로그래머는 new을 호출 할 수 있으며, 뒤에서 함수 포인터를 설정할 수있다.)

+0

고마워, 그건 속임수 였어! 이 점을 이해하기 위해 약간의 시간이 걸렸지 만 "mytest * me"는 내가 사용하는 클래스의 첫 번째 매개 변수와 일치해야합니다. 또한 ifdef는 조금 단순화 될 수 있습니다. "(* name)"및 "name"을 사용하고 "int MEMBER (func1) (mytest * me, int);"와 같은 것을 사용하고 있습니다. – Michael

+0

매개 변수의 이름이 아닌 형식 만 일치시킬 수는 있지만, 어떤 점에서 "this"포인터가 아닌 함수에 하나를 전달하려고한다고 가정합니다. 일관된 이름을 사용하는 것보다 이상적이지 않은 각각의 경우에 대해 특별한 typemap을 작성하는 사업에 착수하십시오. – Flexo

관련 문제