我目前正在開發一個項目,該項目需要開發一個本機DLL(使用C++)以供Java應用程序訪問。我選擇了JNA進行橋接工作,並且遇到了將正確的int值從Java傳遞到C++函數的問題。如何使用JNA將int作爲Java的C++函數參數傳遞
簡單地說,我有一個接受一個int值在C參數++的函數: (代碼被剝離和方法被重命名爲保持機密性)
JAVALINK_EXPORT SomeStructure WINAPI GetSomeStructureFromIndex(int index) {
std::string debugMsg("Received index of ");
debugMsg.append(toString(index));
OutputDebugString(debugMsg.c_str());
SomeStructure result = defaultStructure;
if (index >= 0 && index < structListSize)
result = structList[index];
return result;
}
toString
是轉換的值的簡單方法的任何數據類型爲std::string
使用std::stringstream
。實現如下:
template <class T>
inline std::string toString (const T& t) {
std::stringstream ss;
ss << t;
return ss.str();
}
SomeStructure
從我使用的代碼的實際結構改名。 structList
是一組SomeStructure
。 structListSize
和structList
都是共享內存中的全局變量。
這是在Java接口的DLL方法簽名:
SomeStructure.ByValue GetSomeStructureFromIndex(int index);
這是我使用的方法在Java中測試用例:
SomeStructure.ByValue received = library.GetSomeStructureFromIndex(1);
library
是一個實例使用Native.loadLibrary
生成DLL文件的接口(StdCallLibrary
的子類)。當上面的代碼中的Java執行時,我得到類似以下的輸出在我的Windows調試輸出:然後
Received index of 86701080
(該程序將在遇到訪問衝突錯誤,如果我省略了檢查index
與在從陣列中獲得結構之前的行if (index >= 0 && index < structListSize)
)
86701080
可以是任意的值。我意識到它根據導出函數的簽名而改變。我在這裏錯過了什麼嗎?功能適當地接收的1
期望值已經函數簽名被void PrintIndex(int index)
EDIT(0):我已經修改了示例代碼的實際代碼更緊密地匹配。編輯(1):根據@ technomage的指針我開始使用ByValue
所有方法簽名和變量收集返回的結構。編輯(2):與C++中的SomeStructure
結構相比,Java類SomeStructure
有一個額外的變量和一個Java方法。我目前正在測試這是否是造成這種差異的原因。
問題迎刃而解
@technomage解釋說,C++函數來解釋它的參數和因爲預計到,所使用的結構的大小作爲返回類型(以及那些用作函數參數返回值)不應該與Java相對應。這可以在SomeStructure
的情況下用C++ sizeof(SomeStructure)
和Java用SomeStructure.size()
來檢查。
基本上,發生的事情是SomeStructure
結構的大小與其Java表示不同。 SomeStructure
包含如圖所示在下面的代碼一個固定長度的數組:
#define MAX_LIST_SIZE 256
typedef struct {
int list[MAX_LIST_SIZE];
int length;
} SomeStructure;
然而,Java表示沒有指定固定長度數組的大小。 list
已初始化爲包含單個值0
。
package model;
import com.sun.jna.Structure;
public class SomeStructure extends Structure {
public static class ByValue extends SomeStructure implements Structure.ByValue { }
public int[] list = {0};
public int length = 0;
}
我用,而不是下面的替換有故障的初始化語句解決了這個問題:
private static final int MAX_LIST_SIZE = 256;
public int[] list = new int[MAX_LIST_SIZE];
注意:整型常量MAX_LIST_SIZE
聲明private
以保持Java的唯一。
做出所有這些修改後,我的代碼工作正常,不再遇到訪問衝突。
什麼是toString? – Leonidos 2013-02-20 15:30:47
你試過類似 if(index == 1) OutputDebugString(_T(「passed」)); else OutputDebugString(_T(「failed」)); 在這種情況下檢查toString是否正常工作? – 2013-02-20 15:32:07
我修改了這個問題來解釋錯誤不會發生在'toString'中。 – derfshaya 2013-02-20 16:03:58