JNA: how to deal with unkown structs?

2019-06-08 13:28发布

问题:

If I'm not mistaken, a JNA Structure builds the struct by relying on the public fields of its corresponding Java class, which should extend Structure. My problem is that I need to pass a struct whose declaration is not known beforehand (let's say it's known at runtime). I just have a list of Objects, which the C library expects as a (reference to a) struct. Can I still use the Structure class or must I build a Memory object by hand, dealing with sizes, alignments/packing myself?

For example:

 /* native code */
 typedef struct mystruct {
     int x;
     float y;
 }  mystruct;

 void dosomething(mystruct * s) {
     s->y += s->x;
 }

And in Java:

 ...
 callFunctionWithSt("dosomething",
     new Object[]{Integer.valueOf(2),Float.valueOf(3.0)});
 ...

 void callFunctionWithSt(String funcName, Object[] structVals) {
     NativeLibrary nl = ...
     Pointer arg = ...  // or Memory ... or Structure
     // build structure
     for (Object objJava  : structVals) {
         valJna = convertFromJavaToJnaObject(objJava);
         // fill structure
     }
     f.invoke(arg);
 }

 Object convertFromJavaToJnaObject(Object) {
     // assume we know how to do this
 }

回答1:

If you don't know the content of the struct, then it is referred to as "opaque".

For opaque struct *, you can use com.sun.jna.Pointer to represent the structure address.



回答2:

You can still use Structure. Define your interface method like this:

interface SomeLib {
    public static final SomeLib INSTANCE =
        (SomeLib) Native.loadLibrary("SomeLib", SomeLib.class);

    Pointer getSomeStruct();
}

Then when you call it, you just do this:

Pointer someValue = SomeLib.INSTANCE.getSomeStruct();
// do something here to determine what type it is
SpecificStructure struct = new SpecificStructure(someValue);


标签: java c struct jna