How to make SWIG automatically wrap an emulated pointer "this" to a C-structure?

I have a simple C class that I implemented using function pointers in the structure to implement member functions and passing a pointer to the structure as the first argument for each function, similar to the implicit "this" pointer in 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); 

Now my problem is that when the interface is created in any language that I choose in the interface, I have to explicitly pass the "this" pointer to the object, even if the language itself supports hiding it.

For example, suppose I choose Python. I should do something like this:

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

Where I really want to do it this way:

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

I know that I can just write some code for packaging, but for my actual project I have many functions in the set of objects of the existing C code and multiplying this by each language I want to support is just too much work! Is there a way to get SWIG to do this automatically?

+4
source share
1 answer

You can do this in a language-neutral language in SWIG with only two types, provided that you specify a parameter that will be consistent in the SWIG interface, as well as definitions that allow selective use of the selective application. (If you don't want all pointers to mytest become the "this" pointers by default)

Required file types:

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

A sample validation card is not really intended to be used in this way, but it is the easiest way to get the input code after the arguments have been extracted from the target language and before the actual call.

You can also simplify the module with a macro to avoid having to write and synchronize the mapping between function pointers and member tricks. I ended up with test.h as:

 #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)); }; 

And the corresponding interface file (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" 

(This interface file provides a constructor that "creates" the "object" exactly as a Java programmer would expect - you can call new , and it sets pointers to functions behind the scenes)

+2
source

All Articles