如何在JNA中填充结构数组? [英] How to fill an array of structures in JNA?
问题描述
我正在尝试在JNA中使用以下Windows API:
I am trying to use the following windows API in JNA :
UINT WINAPI GetRawInputDeviceList(
_Out_opt_ PRAWINPUTDEVICELIST pRawInputDeviceList,
_Inout_ PUINT puiNumDevices,
_In_ UINT cbSize
);
UINT cbSize是RAWINPUTDEVICELIST结构的大小,以字节为单位.如何在JNA中知道它?我偶然发现16是正确的值.
UINT cbSize is the size of a RAWINPUTDEVICELIST structure, in bytes. How to know it in JNA? I had accidentally found that 16 is a correct value.
结构如下:
typedef struct tagRAWINPUTDEVICELIST {
HANDLE hDevice;
DWORD dwType;
} RAWINPUTDEVICELIST, *PRAWINPUTDEVICELIST;
pRawInputDeviceList是RAWINPUTDEVICELIST结构的数组,因此在JNA中,我声明以下签名:
pRawInputDeviceList is An array of RAWINPUTDEVICELIST structures so in JNA I'm declaring the following signature :
UINT GetRawInputDeviceList(PointerByReference pRawInputDeviceList, IntByReference puiNumDevices, UINT cbSize);
这是我在JNA中的结构:
And here is my structurre in JNA :
public static class RawInputDeviceList extends Structure {
public HANDLE hDevice;
public DWORD dwType;
public RawInputDeviceList() {
// required for toArray()
}
public RawInputDeviceList(Pointer pointer) {
super(pointer);
read();
}
@Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "hDevice", "dwType" });
}
}
当我获取PointerByReference值以获取指针时,它为null,这有什么问题呢?设备数量正确,但无法正确获取RawInputDeviceList数组.
When i'm getting the PointerByReference value to get the pointer it is null, what is wrong with that? The number of devices is correct bu i can't get the RawInputDeviceList array correctly.
这是完整的测试代码:
public class TestRawInput {
public static void main(String[] args) {
PointerByReference lRawInputDevicesReference = new PointerByReference();
IntByReference lNumDevices = new IntByReference();
UINT lRes = WindowsRawInput.INSTANCE.GetRawInputDeviceList(lRawInputDevicesReference, lNumDevices, new UINT(16));
Pointer lRawInputDevicePointer = lRawInputDevicesReference.getValue();
WindowsRawInput.RawInputDeviceList lRawInputDevice = new WindowsRawInput.RawInputDeviceList(lRawInputDevicePointer);
WindowsRawInput.RawInputDeviceList[] lDevices = (WindowsRawInput.RawInputDeviceList[]) lRawInputDevice.toArray(lNumDevices.getValue());
System.out.println("devices deteced=" + lNumDevices.getValue());
for (int i=0;i<lDevices.length;i++) {
System.out.println("device type: " + lDevices[i].dwType);
}
}
public interface WindowsRawInput extends StdCallLibrary {
WindowsRawInput INSTANCE = (WindowsRawInput) Native.loadLibrary("user32", WindowsRawInput.class, W32APIOptions.DEFAULT_OPTIONS);
UINT GetRawInputDeviceList(PointerByReference pRawInputDeviceList,
IntByReference puiNumDevices, UINT cbSize);
public static class RawInputDeviceList extends Structure {
public HANDLE hDevice;
public DWORD dwType;
public RawInputDeviceList() {
// required for toArray()
}
public RawInputDeviceList(Pointer pointer) {
super(pointer);
read();
}
@Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "hDevice", "dwType" });
}
}
}
}
推荐答案
- 使用
Structure.toArray()
创建一个连续分配的结构数组. - 将该数组的第一个元素传递给您的本机函数.在这种情况下,
struct *
等效于struct []
(本机类型),因此请使用RawInputDeviceList
作为参数类型,而不是PointerByReference 代码>.我不确定为什么他们将单个结构称为列表",但这就是您的窗口.
- 在
puiNumDevices
中传递数组的大小,大概是本机函数将使用实际填写的计数进行更新. - 本机函数将填充内存,并且JNA将在函数返回时将本机内存同步到Java
Structure
. 可以通过调用 -
cbSize
.
Structure.size()
获得- Create an array of continguously-allocated structures using
Structure.toArray()
. - Pass the first element of that array to your native function. In this case,
struct*
is equivalent tostruct[]
(native types), so useRawInputDeviceList
as the argument type instead ofPointerByReference
. I'm not sure why they call the individual structure a "list", but that's windows for you. - Pass the size of your array in
puiNumDevices
, which presumably the native function will update with the count actually filled in. - The native function will fill in the memory, and JNA will sync the native memory to Java
Structure
on function return. cbSize
may be obtained by callingStructure.size()
.
这篇关于如何在JNA中填充结构数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!