2015-04-03 28 views
0

我的Java應用程序使用JNA通過製造商提供的API與設備驅動程序進行通信。 API使用Windows消息進行通信。在執行過程中的一個點上,設備有一組作爲LPARAM傳遞的數據。 LPARAM是指向包含我需要的數據的結構向量的指針。我如何處理JNA中的不透明指針?

在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:回調[email protected]發生以下異常: java.lang.UnsupportedOperationException:該指針是不透明的: 常量@ 0x155f0000在 com.sun.jna.Pointer $ Opaque.read(Pointer.java:1320)在 com.sun.jna.Pointer.getByteArray(Pointer.java:726)在 desktop.IDeal.callback(IDeal.java:199)at sun .reflect.NativeMethodAccessorImpl.invoke0(本機方法)在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在java.lang.reflect中.Method.invoke(Method.java:497)在 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 $ Handle r.invoke(Library.java:232)at com.sun.proxy $ Proxy2.GetMessage(Unknown Source)at win32.Window.run(Window.java:59)at java.lang.Thread.run( Thread.java:745)

我有東西映射正確嗎?如果我沒有辦法將指針的另一端的數據映射到一組Java對象,那麼如何使用Pointer對象來訪問該數據?

回答

1

將回調的簽名更改爲接受IMAGES而不是LPARAM。 JNA將爲您負責轉換。

您還應該考慮命名您的JNA Structure,就像您的本地struct一樣,以避免混淆(使用「ImagesStruct」而不是「IMAGES」)。

使用基於Pointer的構造函數初始化JNA Structure時,最好還是撥打Structure.read()。這確保Java構造函數在構造函數返回之前與本地內存同步。

+0

謝謝你的建議。我添加了以前錯過的'read()'的調用,並且仍然得到*指針是不透明*消息。修改回調來取代IMAGES而不是LPARAM會做一些不同於'new IMAGES(lParam.toPointer())'的東西嗎? – Cypher 2015-04-07 17:13:52

+0

是的,改變回調簽名*會*做一些不同的事情,這就是爲什麼我首先提出的建議。 – technomage 2015-04-07 17:34:54

+0

我問的原因是因爲設備發送了許多消息到這個回調管理的窗口句柄,並且LPARAM經常用於不同類型的數據(主要是int),這些數據不會正確映射到IMAGES對象。因此,如果我無法映射LPARAM - > IMAGES,如果API開發人員確實使用了不透明指針,是否有手動從指針中讀取數據的方法?我已經嘗試了指針對象上的各種方法,比如read(),getByte()等等,它們都會以相同的異常失敗。 – Cypher 2015-04-08 18:11:15

1

我發現在JNA Win32WindowDemo答案:只需使用LPARAM回調,並使用YourStructureHere創建結構(新指針(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);