我的Java应用程序使用JNA通过制造商提供的API与设备驱动程序进行通信。 API使用Windows消息进行通信。在执行期间,设备具有作为LPARAM传递的一组数据。 LPARAM是指向包含我需要的数据的结构向量的指针。
在C ++中,我可以像这样访问这些数据:
ImagesStruct *Images = { 0 };
...
Images = (ImagesStruct *)lParam;
本机ImagesStruct看起来像这样:
typedef struct _CompressedImage
{
BYTE *pBuffer;
int BufferLen;
}
CompressedImage;
typedef struct _ImagesStruct
{
DWORD DocNumber;
CompressedImage *Images;
BOOL SnippetFront;
}
ImagesStruct;
在Java中,我的结构映射如下:
// ImagesStruct
public class IMAGES extends Structure {
public int DocNumber;
public COMPRESSED_IMAGE.ByReference Images; // pointer
public boolean SnippetFront;
public IMAGES() { super(); }
public IMAGES(Pointer p) { super(p); }
@Override
protected List getFieldOrder() {
return Arrays.asList("DocNumber", "Images", "SnippetFront");
}
}
// CompressedImage
public class COMPRESSED_IMAGE extends Structure {
public Pointer pBuffer; // pointer
public int BufferLen;
public COMPRESSED_IMAGE() { super(); }
public COMPRESSED_IMAGE(Pointer p) { super(p); }
@Override
protected List getFieldOrder() {
return Arrays.asList("pBuffer", "BufferLen");
}
public static class ByReference extends COMPRESSED_IMAGE implements Structure.ByReference {
public ByReference() { super(); }
public ByReference(Pointer p) { super(p); read(); }
}
}
以下是我尝试在Java中访问该数据的众多方法之一
Pointer p = lparam.toPointer(); // this works
IMAGES pImages = new IMAGES();
IMAGES[] pa = (IMAGES[]) pImages.toArray(pImages.size()); // error here
我尝试的所有内容(包括上述内容)似乎都会产生相同的错误消息:
JNA:Callback desktop.IDeal@1175f37引发了以下异常: java.lang.UnsupportedOperationException:此指针不透明: const @ 0x155f0000 at com.sun.jna.Pointer $ Opaque.read(Pointer.java:1320)at com.sun.jna.Pointer.getByteArray(Pointer.java:726)at desktop.IDeal.callback(IDeal.java:199)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在java.lang.reflect.Method.invoke(Method.java:497)at com.sun.jna.CallbackReference $ DefaultCallbackProxy.invokeCallback(CallbackReference.java:470) 在 com.sun.jna.CallbackReference $ DefaultCallbackProxy.callback(CallbackReference.java:500) at com.sun.jna.Native.invokeInt(Native Method)at com.sun.jna.Function.invoke(Function.java:384)at com.sun.jna.Function.invoke(Function.java:316)at com.sun.jna.Library $ Handler.invoke(Library.java:232)at com.sun.proxy。$ Proxy2.GetMessage(未知来源)at win32.Window.run(Window.java:59)at java.lang.Thread.run(Thread.java:745)
我是否正确映射了事物?如果我无法将指针另一端的数据映射到一组Java对象,那么如何使用Pointer
对象来访问该数据呢?
答案 0 :(得分:1)
更改回调的签名以接受IMAGES
而不是LPARAM
。 JNA将为您处理转换。
您还应该考虑将JNA Structure
命名为与您的原生struct
完全相同,以避免混淆(使用" ImagesStruct"而不是" IMAGES")
使用基于Structure.read()
的构造函数初始化JNA Structure
时,调用Pointer
也是一种很好的做法。这可确保Java字段在构造函数返回之前与本机内存同步。
答案 1 :(得分:1)
我在JNA Win32WindowDemo中找到了答案:只需使用LPARAM回调并使用YourStructureHere(new Pointer(lParam.longValue()))构造函数创建结构:
public LRESULT callback(HWND hwnd, int uMsg, WPARAM wParam, LPARAM lParam) {
if (commandCompletionMessages.contains(uMsg) || eventMessages.contains(uMsg)){
WFSRESULT wfsresult = new WFSRESULT(new Pointer(lParam.longValue()));
(...)
}
return User32.INSTANCE.DefWindowProc(hwnd, uMsg, wParam, lParam);