記錄下這幾天用jna3.5.0調c++寫的dll的經歷html
os:win7java
用jna調dll首先須要一個dll文件並有可調的方法,而後根據方法的名稱,參數,返回值編寫一個interfacec++
c++須要包含一個頭文件,方法須要用extern "C" __declspec(dllexport)修飾git
c與java類型的對應關係詳見https://java-native-access.github.io/jna/3.5.0/javadoc/的Marshalling/Unmarshalling (Java/Native Type Conversions)這一節github
example:windows
Hello.h數組
extern "C" __declspec(dllexport) char** hello();
Hello.cppjvm
char** hello(){ char** result = new char*[3] result[0] = "123"; result[1] = "321"; result[2] = NULL;// 注意,數組的最後一個元素必須爲NULL return; }
以上是c++源碼,打包成Hello.dll放到某個目錄下,好比這裏移動到D:\Hello\Hello.dll,注意平臺要選擇x64,不然64位jdk可能會找不到庫測試
Hello.java編碼
public interface Hello{ String[] hello(); }
Main.java
public class Main{ public static void main(String[] args){ Native.setProtected(true);// 等效於jna.protected=true,這項設置會使本地方法發生異常時生成java異常,若是爲false則本地方法發生異常時會使jvm崩潰,沒法try-catch,默認false,注意此方法只適合在windows上測試時使用 NativeLibrary.addSearchPath("Hello", "D:\\Hello");// 注意這裏參數一不帶dll後綴,參數二是文件所在的文件夾路徑而不是文件路徑 Hello hello = (Hello) Native.loadLibrary("Hello", Hello.class); System.out.println(Arrays.toString(hello.hello())); } }
Native.loadLibrary(String, Class);
這個方法第一個參數填加載dll的名稱,不含.dll後綴。
搜索dll的路徑是: 1)項目的根路徑 2)操做系統的全局路徑、 3)path指定的路徑。
摘自https://blog.csdn.net/jimmy609/article/details/19076557
這裏由於調用了addSearchPath方法因此不用在意這些限制,dll能夠放在任意位置
配合visual studio調試:
首先dll須要以debug模式編譯,而後以debug模式運行java,在調用本地方法以前打好斷點,在vs中選擇調試-附加到進程,選擇java的進程,進程id能夠經過ManagementFactory.getRuntimeMXBean.getName()
方法看到,前面的數字就是進程id,在vs中打好斷點,放開java的斷點就能夠進來了。
另外提一句,String和char*之間會根據jna.encoding(默認utf8)轉換,而中文系統是用的GBK編碼,中文會亂碼,能夠經過手動設置jna.encoding參數解決,不過這裏推薦使用wchar_t替換char,WString替換String