![](/img/trans.png)
[英]How to pass List<T> from Java to a C++ std::vector function parameter using JNA
[英]How to pass int as a C++ function parameter from Java using JNA
我目前正在從事一個項目,該項目需要開發一個本機DLL(在C ++中)才能由Java應用程序訪問。 我已選擇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
都是共享內存中的全局變量。
這是DLL的Java接口中的方法簽名:
SomeStructure.ByValue GetSomeStructureFromIndex(int index);
這就是我將Java中的方法用於測試用例的方式:
SomeStructure.ByValue received = library.GetSomeStructureFromIndex(1);
library
是使用Native.loadLibrary
生成的DLL文件( StdCallLibrary
子類)的接口的實例。 當上述代碼在Java中執行時,我的Windows調試輸出中得到類似以下輸出的內容:
Received index of 86701080
(如果我在從數組中獲取結構之前省略了對if (index >= 0 && index < structListSize)
行的index
檢查,則程序將繼續遇到訪問沖突錯誤)
86701080
可以是任意值。 我意識到它會根據導出函數的簽名而變化。 我在這里想念什么嗎? 如果函數簽名為void PrintIndex(int index)
該函數正確接收期望值為1
的void PrintIndex(int index)
EDIT(0):我修改了示例代碼以使其更接近實際代碼。
EDIT(1):根據ByValue
的指針,我已開始將ByValue
用於所有方法簽名和收集返回結構的變量。
EDIT(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。
進行所有這些修改后,我的代碼可以正常工作,不再遇到訪問沖突。
“ WINAPI”表示stdcall調用約定,但是您必須確定本地的宏定義才能確定。 如果是這樣,則需要StdCallLibrary
而不是Library
。 這可能會影響您的傳入index
參數。
您還將復制結構(通過值語義),而不是指向它的指針。 當按值傳遞結構或按值返回結構時,您需要告訴JNA您正在這樣做 。
編輯
確保SomeStructure.size()
與本機sizeof(SomeStructure)
匹配。 通常,實現按值返回的結構,以便調用方在堆棧上分配內存,並將隱式指針傳遞給被調用方,然后該被調用方將其寫入該內存。 如果調用方和被調用方在該內存大小上存在分歧,則可能影響堆棧上的其他內容(例如,參數和返回值)。 您還可以向函數添加更多參數,並打印它們的值(十六進制),以大致了解堆棧中的內容。 如果傳入可識別的參數(例如0x12345678),通常會很清楚是什么在錯誤的方向推動或拉動堆棧。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.