2015-04-25 66 views
2

我有一個C函數(編譯成一個DLL),需要一個WinDef.RECT對象,並打印出的四個座標:清分WinDef.RECT結構在JNA

DllExport void Test(RECT rect) 
{ 
    printf("Rect: %i, %i, %i, %i", rect.top, rect.left, rect.bottom, rect.right); 
} 

在Java(JNA)側我試圖傳遞一個WinDef.RECT如下:

WinDef.RECT rect = new WinDef.RECT(); 
rect.bottom=0; 
rect.left=0; 
rect.right=0; 
rect.top=0; 
jna.INSTANCE.Test(rect); 

不過,我只是得到廢話數字出來(這並不一致,具體費用每次),例如:

Rect: -857788769, 11343200, 8044544, 8044544 

我假設我沒有在JNA端正確定義RECT(C++函數可以從同一個dll中的其他本地函數中調用),但除此之外,我有點卡住了!

+1

我注意到,當我使用一個32位JRE與32位版本的DLL時,我遇到了同樣的問題,而一切正常工作與64位版本。 – regulus

+0

@regulus感謝您的觀察 - 你會建議這是一個JNA錯誤在這種情況下? (不幸的是,我的用例將我限制爲32位堆棧。) – berry120

+0

請注意,w32 API在32位系統上使用['stdcall'](http://stackoverflow.com/questions/297654/what-is-stdcall)位,但不是64位。確保你的本地庫使用'stdcall',確保你的JNA映射實現了'StdCallLibrary'。 – technomage

回答

0

我有一個有用的答案在JNA郵件列表:

你的母語簽名要求結構和您的JNA映射默認爲結構*語義。更改您的原生sig或使用Structure.ByValue;除非明確需要,否則struct *是首​​選。

在我來說,我需要本地庫保持不變,因此該解決方案被宣佈的WinDef.RECT子類,並標記它Structure.ByValue

public static class RectByValue extends WinDef.RECT implements Structure.ByValue {} 

這可能則代替WinDef.RECT使用,並且似乎都沒有問題。

請注意,雖然此修復程序對我來說可以正常工作,但其他人也有其他報告 - 如下面的註釋中所示,切換到LPRECT是另一種可能的修復方法。

+1

在我的情況下使用ByValue沒有幫助,但在我閱讀你的答案後,我試着將我的方法簽名更改爲解決問題的LPRECT。我仍然覺得這裏有一個JNA bug。 – regulus

+0

@regulus嗯,這很有趣 - 我只是嘗試在64位堆棧上重新編譯/運行,我實際上得到了與32位堆棧相同的結果(不管我第一次嘗試的方式如何,但是使用'ByValue'修復了它。 )如果它在所有系統上似乎都不可靠工作,那麼現在我很厭倦推出此代碼! (無論其他人遇到同樣的問題,我都會更新我的答案) – berry120

+0

請注意,您需要更改映射的函數簽名*和*實際傳遞給標記爲「Structure.ByValue」類型的對象。函數簽名是決定數據如何傳遞給本地代碼的原因,顯然如果你弄錯了,你可能會崩潰虛擬機,或者至多得到假數據。 – technomage