Reputation: 608
I need to access native C++ code .dll from Java application. native int function works well, but for Linkedlist Struct I cannot find any reference on the Internet how to declare the java interface
this C++ code
struct usb_relay_device_info
{
unsigned char *serial_number;
char *device_path;
usb_relay_device_type type;
usb_relay_device_info* next;
};
int EXPORT_API usb_relay_init(void);
struct usb_relay_device_info EXPORT_API * usb_relay_device_enumerate(void);
int EXPORT_API usb_relay_device_open(struct usb_relay_device_info* device_info);
This is the java part
public interface JNI extends Library {
JNI INSTANCE = (JNI) Native.loadLibrary("usb", JNI.class);
public static class usb_relay_device_info extends Structure {
public static class DeviceInfo extends usb_relay_device_info implements Structure.ByValue {
}
public byte[] serial_number = new byte[1024];
public String device_path;
public int type;
}
int usb_relay_init();
usb_relay_device_info.DeviceInfo usb_relay_device_enumerate();
int usb_relay_device_open(usb_relay_device_info.DeviceInfo deviceInfo);
}
I already created just the struct at the java code (NOT the Linkedlist Struct). So when I call the function the values are not showing up because it supposed to be a list (linkedlist in C++)
Upvotes: 0
Views: 161
Reputation: 9091
You say "I cannot find any reference on the Internet how to declare the java interface" but there are plenty of references, including JNA's Overview, linked to the main project page.
There you will find that char *
is a C String and should be mapped to Java's String
.
The usb_relay_device_type
mapping has to be referenced in the API that you're mapping. In this case it is an enum
type, which is an integer, so int
is probably appropriate here. (There are cases where it can be a smaller integer value like short
or byte
but those are rare.)
As for the pointer to the next device, that is also referenced on the overview page under struct*
. The link (or explicitly) links to Structure.ByReference
. That may not be obvious, but the JNA FAQ, also linked on the main JNA project page, amplifies. If it's still not clear, here's a summary:
usb_relay_device_info.ByReference
. (You'll also need to change the structure declaration to implement ByReference -- the JNA overview, linked above, has an example of this.)usb_relay_device_open()
, the opposite is true: the "By Reference" is the default, and you only need to explicity specify "By Value" if that's relevant. In this case, it's not -- the native declaration includes the pointer: (usb_relay_device_info*
) so you want the ByReference behavior. You can just put usb_relay_device_info device_info
there and the ByReference will be implicit. Or, if you prefer (it's not needed) you could do usb_relay_device_info.ByReference device_info
and it would just be redundant.So in summary your structure mapping should be:
class usb_relay_device_info extends Structure {
public static class ByReference extends usb_relay_device_info implements Structure.ByReference { }
public String serial_number;
public String device_path;
public int type;
public usb_relay_device_info.ByReference next;
};
You'll need to add the FieldOrder, preferably using an annotation.
Upvotes: 1