简体   繁体   English

我如何处理JNA中的不透明指针?

[英]How do i deal with opaque pointers in JNA?

My Java application uses JNA to communicate with device drivers through the manufacturer's supplied API. 我的Java应用程序使用JNA通过制造商提供的API与设备驱动程序进行通信。 The API communicates using Windows Messages. 该API使用Windows消息进行通信。 At a point during execution, the device has a set of data passed as an LPARAM. 在执行过程中的某个时刻,设备具有一组作为LPARAM传递的数据。 The LPARAM is a pointer to a vector of structures that contains the data I need. LPARAM是指向包含我所需数据的结构向量的指针。

In C++, I can access this data like this: 在C ++中,我可以像这样访问此数据:

ImagesStruct *Images = { 0 };
...
Images = (ImagesStruct *)lParam;

The native ImagesStruct looks like this: 本机ImagesStruct看起来像这样:

typedef struct _CompressedImage
{
  BYTE *pBuffer;
  int BufferLen;
}
CompressedImage;

typedef struct _ImagesStruct
{
  DWORD DocNumber;
  CompressedImage *Images;
  BOOL SnippetFront;
}
ImagesStruct;

In Java, I have the Structures mapped like this: 在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(); }
    }
}

Here is one of the many ways I've tried to access that data in Java 这是我尝试用Java访问该数据的多种方法之一

Pointer p = lparam.toPointer(); // this works
IMAGES pImages = new IMAGES();
IMAGES[] pa = (IMAGES[]) pImages.toArray(pImages.size()); // error here

Everything I try, including the above, seems to result in the same error message: 我尝试的所有操作(包括上述操作)似乎都导致了相同的错误消息:

JNA: Callback desktop.IDeal@1175f37 threw the following exception: java.lang.UnsupportedOperationException: This pointer is opaque : 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) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at com.sun.jna.CallbackReference$DefaultCallbackProxy.invokeCallback(CallbackReference.java:470) at 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 JNA:回调desktop.IDeal@1175f37引发以下异常:java.lang.UnsupportedOperationException: 该指针不透明 :com.sun.jna.Pointer $ Opaque.read(Pointer.java:1320)处的const @ 0x155f0000桌面的.jna.Pointer.getByteArray(Pointer.java:726)。sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)处的sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)处的IDeal.callback(IDeal.java:199) :62),位于com.sun.jna.CallbackReference $ DefaultCallbackProxy.invokeCallback(CallbackReference.java.lang.reflect.Method.invoke(Method.java:497)处的sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)处。 com.sun.jna.Function.invoke(Function.com上的com.sun.jna.Native.invokeInt(Native Method)处的com.sun.jna.CallbackReference $ DefaultCallbackProxy.callback(CallbackReference.java:500) java:384)com.sun.jna.Function.invoke(Function.java:316)com.sun.jna.Library $ Handler.invoke(Library.java:232)com.sun.proxy。$ Proxy2 .GetMessage(Unknown Source) at win32.Window.run(Window.java:59) at java.lang.Thread.run(Thread.java:745) .getMessage(未知源)在win32.Window.run(Window.java:59)在java.lang.Thread.run(Thread.java:745)

Do I have things mapped correctly? 我的东西映射正确吗? If there's nothing I can do to map that data at the other end of the pointer to a set of Java objects, how do I use the Pointer object to access that data? 如果无法执行任何操作以将指针另一端的数据映射到一组Java对象,该如何使用Pointer对象访问该数据?

Change the signature of your callback to accept IMAGES instead of LPARAM . 更改回调的签名以接受IMAGES而不是LPARAM JNA will take care of the conversions for you. JNA将为您处理转换。

You should also consider naming your JNA Structure exactly like your native struct in order to avoid confusion (use "ImagesStruct" instead of "IMAGES"). 你也应该考虑命名您的JNA Structure酷似您的本机struct ,以避免混淆(使用“ImagesStruct”而不是“图像”)。

It's also good practice to call Structure.read() when initializing a JNA Structure using the Pointer -based constructor. 使用基于Pointer的构造函数初始化JNA Structure时,调用Structure.read()也是一个好习惯。 That ensures the Java fields are in synch with native memory before the constructor returns. 这样可以确保在构造函数返回之前,Java字段与本地内存保持同步。

I found the answer in the JNA Win32WindowDemo: Just use the LPARAM callback and create your Structure using the YourStructureHere(new Pointer(lParam.longValue())) constructor: 我在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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM