Java JNA 链表声明

Java JNA Linkedlist declaration

我需要从 Java 应用程序访问本机 C++ 代码 .dll。本机 int 函数运行良好,但对于 Linkedlist Struct,我无法在 Internet 上找到任何参考如何声明 java 接口

此 C++ 代码

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

这是java部分

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

}

我已经在 java 代码中创建了结构(不是 Linkedlist 结构)。所以当我调用函数时,值没有显示,因为它应该是一个列表(C++ 中的链表)

你说“我在 Internet 上找不到任何关于如何声明 java 接口的参考资料”,但是有很多参考资料,包括 JNA 的 Overview、linked 到主项目页面。

在那里你会发现 char * 是一个 C 字符串,应该映射到 Java 的 String

必须在您正在映射的 API 中引用 usb_relay_device_type 映射。在这种情况下,它是一个 enum 类型,它是一个整数,因此 int 在这里可能是合适的。 (在某些情况下,它可以是较小的整数值,如 shortbyte,但这种情况很少见。)

至于指向下一个设备的指针,在struct*下的概述页面中也有引用。 link(或明确地)link 到 Structure.ByReference。这可能不是很明显,但是 JNA FAQ,也在 JNA 项目主页面上 linked,放大了。如果还是不清楚,这里总结一下:

  • 默认情况下,在结构中列为字段的结构会被“按值”处理,即完整结构及其字段按行插入。要获得此行为,您只需声明结构名称即可。
  • 如果您想要相反的行为(通过引用),那么您必须明确声明,JNA 会将指针映射到别处的结构。这是你的情况,正确的结构映射是usb_relay_device_info.ByReference。 (您还需要更改结构声明以实现 ByReference——上面 linked 的 JNA 概述有一个这样的例子。)
  • 在函数参数中使用时,例如 usb_relay_device_open(),情况正好相反:“按引用”是默认设置,如果相关,您只需要明确指定“按值”。在这种情况下,它不是——本机声明包含指针:(usb_relay_device_info*) 所以您需要 ByReference 行为。您可以将 usb_relay_device_info device_info 放在那里,ByReference 将是隐式的。或者,如果您愿意(不需要),您可以 usb_relay_device_info.ByReference device_info 并且它只是多余的。

所以总而言之,您的结构映射应该是:

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

您需要添加 FieldOrder,最好使用注释。