Callback as parameter of C structure - Java shell generation

I have no problem with simple callbacks when a free function is passed as a parameter to another, thanks @flexo .

But suppose the bit is a more complex C interface:

typedef struct { int id; const char* name; } Item; typedef struct { int value; Items_Callback callback; void *context; } Items_Call; typedef int (*Items_Callback)(const Item *item, void *context); int Items_create(const Item *item, Items_Call *call) { ... call->callback(item, call->context); ... } 

I intend to generate some pretty Java wrapper for code like this. I believe that as a result

 class Item { public int id; public String name; } class Items_Call { public int value; public Object context; public Interface callback; public void setInterface(Interface i){ callback=i; }; } public interface Interface { public int Items_Callback(Item item, Object context); } int Items_create(Item item, Items_Call call) { ... call.callback.Items_Callback(item, call.context); ... } 

I understand that SWIG has problems generating pure Java interfaces, but I think this is not a big problem. The problem is that I have no idea how to reinterpret such a nested structure for acceptable Java code.

+7
java c swig jni
source share
1 answer

Not SWIG, but the following works with JavaCPP (which is not related to the kind of utility JNA and works wherever the JNI works):

 // items.h typedef struct { int id; const char* name; } Item; typedef int (*Items_Callback)(const Item *item, void *context); typedef struct { int value; Items_Callback callback; void *context; } Items_Call; int Items_create(const Item *item, Items_Call *call) { // ... call->callback(item, call->context); // ... return 0; } 

And in Java:

 import com.googlecode.javacpp.*; import com.googlecode.javacpp.annotation.*; @Platform(include="items.h") public class Items { static { Loader.load(); } public static class Item extends Pointer { public Item() { allocate(); } private native void allocate(); public native int id(); public native Item id(int id); @Cast("const char*") public native BytePointer name(); public native Item name(BytePointer name); } public static class Items_Callback extends FunctionPointer { protected Items_Callback() { allocate(); } private native void allocate(); public native int call(@Const Item item, Pointer context); } public static class Items_Call extends Pointer { public Items_Call() { allocate(); } private native void allocate(); public native int value(); public native Items_Call value(int value); public native Pointer context(); public native Items_Call context(Pointer context); public native Items_Callback callback(); public native Items_Call callback(Items_Callback value); public void setInterface(Items_Callback i) { callback(i); } } public static native void Items_create(Item item, Items_Call call); public static void main(String[] args) { BytePointer s = new BytePointer("Hello"); Item i = new Item(); i.id(42); i.name(s); Items_Callback cb = new Items_Callback() { public int call(Item item, Pointer context) { System.out.println(item.id() + " " + item.name().getString()); return 0; } }; Items_Call ic = new Items_Call(); ic.callback(cb); Items_create(i, ic); // if we remove these references, the GC may prematurely deallocate them s.deallocate(); cb.deallocate(); } } 

Which displays the expected result:

 42 Hello 

Disclaimer: I am the author of JavaCPP :)

+4
source share

All Articles