cs4r
cs4r

Reputation: 624

Get a Struct from C (By Reference)

Assume I have the next C code snippet and I want to call it from Java using JNA.

typedef struct {
            int                     bit_a;
            int                     bit_b;
} * bit_handle;

bit_handler handle_open(const char *name, int prop);

For such a purpose I have written the next Java code snippet:

Java code:

 public interface BitLibrary extends Library {
        BitLibrary INSTANCE = (BitLibrary) Native.loadLibrary("bitlibrary", BitLibrary.class);
        Pointer handler_open(char* name, int prop);
    }

And it works perfectly, but instead of a Pointer I would like to retrieve a BitHandle object (see implementation below) by reference, because bit_handle in the previous C code is a pointer. How could I do that? I have tried something that looks like this example but I got a ClassCastException that says java.lang.reflect.Field cannot be cast to java.lang.Comparable and I am a bit clueless because from the logical point of view should work, but it doesn't. Am I missing something?

BitHandle implementation:

    public static class BitHandle extends Structure {
        public int bit_a;
        public int bit_b;

        public BitHandle(Pointer peer){
            super(peer);
        }

        @Override
        @SuppressWarnings({ "rawtypes", "unchecked" })
        protected List<?> getFieldOrder() {
            List fieldList = new ArrayList(super.getFieldList());
            fieldList.addAll(Arrays.asList("bit_a", "bit_b"));
            return fieldList;
        }

    }

Upvotes: 0

Views: 119

Answers (1)

cs4r
cs4r

Reputation: 624

Solution found, thanks to @user2864740 suggestions. The key was to disregard getFieldOrder() javadoc and implement it as below:

public class BitTest {

    public interface BitLibrary extends Library {
        BitLibrary INSTANCE = (BitLibrary) Native.loadLibrary("bit", BitLibrary.class);

        public static class BitHandle extends Structure {
            public int bit_a;
            public int bit_b;
            public static class ByReference extends BitHandle implements Structure.ByReference {}


            @Override
            protected List getFieldOrder() {
                List<String> fieldList = new ArrayList<>();
                fieldList.addAll(Arrays.asList("bit_a", "bit_b"));
                return (List) fieldList;
            }

        }


        BitHandle.ByReference bit_open(String drivername, int lun);

    }

    public static void main(String[] args) {
        BitLibrary.BitHandle.ByReference pointer = BitLibrary.INSTANCE.Bit_open("CIBM_LINUX", 0);
   }

}

Upvotes: 1

Related Questions