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
在这里可能是合适的。 (在某些情况下,它可以是较小的整数值,如 short
或 byte
,但这种情况很少见。)
至于指向下一个设备的指针,在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,最好使用注释。
我需要从 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
在这里可能是合适的。 (在某些情况下,它可以是较小的整数值,如 short
或 byte
,但这种情况很少见。)
至于指向下一个设备的指针,在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,最好使用注释。