類型對應
- 簡單類型
- 參考官方文檔中的對應表
- 簡單類型的數組做參數時也同樣用對應類型的數組即可,做返回值時需要用 Memory 或 Buffer 類來代表,以便處理內存
- c++中的多維數組需要按總長度對應成 java 中的一維數組
- 字符串
- java 中的字符串一般映射到C++的 char*,JNA 會自動處理
- 需要注意Unicode(帶中文的)字符串自動轉換成 char* 時會使用平臺默認編碼
- 另外,對于C++中的wchar_t類型,應該用專用的 WString 類做映射
- 指針類型
- JNA 提供了 Pointer 類和一系列子類,它有的write, read, getXXX, setXXX 等方法,用來操作指向的那片內存。所以要注意比如 getByteArray()這種操作是沒有內存 copy的,只是返回一個引用。
- 簡單類型如 int 的指針可以直接使用 ByReference 類的子類代表
- 結構體
- 需要自己定義一個提供了一個繼承自 Structures 的java 類,用來對應struct。當參數是 struct數組時,在 java 中也直接用對應類的數組。
- 用作參數或返回值時,這個類的實例相當于一個C++ struct 的指針,如果這時方法的參數或返回值不是指針,而是傳值調用,則對應在 java 中使用 MyStruct.ByValue。
- 用作另一個 struct 的字段時,
- 結構體這段比較復雜,不清楚的看官方文檔
內存處理
- 一般指針類型的參數,當不需要開辟內存,或者只是接收從 C++ 程序開辟的內存(如返回值或輸出參數)時 應該用 Pointer 類型或它的子類型。
- 當需要在 java 中開辟一塊內存區域傳給 C++ 程序時,應該使用Pointer 的子類 Memory。JVM 在GC時會自動釋放Memory中開辟的內存區域。
- Pointer 和子類的 write 和 read 方法使用時注意第一個參數是偏移量 單位是字節,最后一個參數長度是按 java 中的數組長度。比如第一次寫入一個長度為2的整形數組,調用時最后一個參數應該為2。因為每一個整形數占4字節,第二次繼續寫入的時候,第一個偏移量參數應該在原來的基礎上加2*4=8。
- 當C++代碼中開辟了內存空間,并作為參數返回時,使用后用如下方式釋放:
Native.free(Pointer.nativeValue(yourPointer));
編譯運行
- C++代碼中一定要加上 extern "C",保證編譯后的名稱和源代碼中一樣,否則會報找不到標識符的錯誤。
- 動態鏈接庫一般編譯成 lib[名稱].[擴展名] 的形式
- 名稱是你自己取的名字
- 擴展名根據平臺有所不同,linux是 so,mac 是 dylib,windows 是 dll
- 編譯命令
- Linux/Mac下 g++ -dynamiclib -o 目標文件名 *.cpp
- java 程序運行之前要設置動態鏈接庫所在路徑的環境變量 export LD_LIBRARY_PATH=[yourPath]
參考資料
上面的整理知識算是些常見情況和要點的匯總,細節可以再參考官方文檔,其實還是比較詳細的:官方文檔