本文環境:IntelliJ idea2018.2+Visual Studio 2017

專案:JavaWEB+Win32控制檯

宣告:本人是個新手小白。因為專案是C++演算法寫的,但是要用網頁呼叫,所以先學習JavaWEB呼叫C++程式作為嘗試。參考了網上的一些教程,結合自己的理解與出現的錯誤,寫成總結日後參考。不足之處請提出。

首先明確本文的步驟:

  1. 在Java中新建一個類。
  2. 生成JNI標頭檔案。(此處有兩種方法:2.1手動輸入javah命令生成標頭檔案、2.2 一鍵生成標頭檔案)
  3. 在VS2017下引入標頭檔案。
  4. 將dll新增進JavaWEB工程,成功執行。

1.在Java中新建類

利用IntelliJ  idea新建一個Java工程,在src中新建一個Java類,名稱命名“testNative”。之後彈出testNative.java。

在testNative.java中寫如下程式:

函式System.loadLibrary()是載入dll(windows)或so(Linux)庫,只需名稱即可,無需加入檔名字尾(.dll或.so)。

native關鍵字將函式sayHello()宣告為本地函式,由C/C++實現。具體的實現就在hello.dll(Windows平臺)或hello.so(Linux平臺)中。

2.生成JNI標頭檔案

  • 2.1 手動輸入javah命令生成標頭檔案
  • 2.2 一鍵生成標頭檔案

2.1 手動輸入javah命令生成標頭檔案

JNI生成標頭檔案是通過JDK中提供的javah來完成,javah在 {JDKHome}/bin目錄中。用法如下:

javah -jni -classpath (搜尋類目錄) -d (輸出目錄) (類名)

例如,將E:\Porject\out\com\huachao\java目錄中的HelloJNI.class生成標頭檔案,並放入到E:\Project\jni中:

javah -jni -classpath  E:\Porject\out\com\huachao\java -d E:\Project\jni  com.huachao.java.HelloJNI.java

需要注意的是,使用javah來生成標頭檔案(.h)時,-classpath指定的是編譯後的java檔案(.class)的目錄,而不是原始檔(.java)的目錄,因此在使用javah指令之前,先build一下專案(或直接執行一下)。此時會生稱out目錄,所有編譯後的檔案都會存放在這個目錄中。

Build之後:project下的out中多出來production及以下內容。

生成out目錄之後的:

接下來,直接在IDEA的Terminal視窗執行javah,寫命令如下:

(沒有Terminal視窗的可以在File→Plugins→Terminal 勾選它,點選Apply,點選Restart即可
如果是要啟動terminal則必須先做完上面動作,才可以點選Tools→Open Terminal... 來達到開啟terminal)

執行javah指令

javah -jni -classpath (搜尋類目錄) -d (輸出目錄) (類名)

按回車鍵執行,在終端(Terminal)輸入如上命令之後,目錄出現了jni資料夾,下面對應有標頭檔案

開啟testNative.h, 函式名稱是有規律的,即Java_<>_<類名>_<函式名>

接下來我們就要實現

至此,生成標頭檔案的第一種方法就結束了。還有另一種一鍵生成的方法更簡單請往下看。

2.2 一鍵生成標頭檔案

如果目錄層次很深,或者是有多個需要生成標頭檔案的class檔案,這工作量太大了,當然你可以通過寫個小程式來實現。

但是這裡有個更便捷的方法。點選File>Settings>Tools>External Tools

External Tools

新增一個新的External Tools:

新增一個先的External Tools

在testNative.java檔案中  點選右鍵>External Tools>Generate Header File

點選生成,可以看到Terminal視窗會自動執行指令。跟2.1小節的指令一模一樣。

3.在VS2017下引入標頭檔案

首先開啟Visual Studio 2017,新建一個Win32控制檯。

Win32專案現在位於“新建專案”對話方塊中的Windows桌面類別下面,在此類別下面還有一個新的Windows桌面嚮導,可以建立新的Win32專案

雙擊 Windows桌面嚮導,開啟如下

注意此處不要勾選預編譯標頭。

初始目錄:

拷貝三個.h檔案到VS專案中:

將在Java JDK的安裝目錄下,我的目錄為C:\Program Files\Java\jdk1.8.0_181\include下的jni.h,

與C:\Program Files\Java\jdk1.8.0_181\include\win32下的jni_md.h,

與第一步生成的testNative.h, 一共三個標頭檔案,拷貝到當前VS專案目錄下,拷貝之後的目錄為:

testNative.h中的 #include<jni.h> 改為 #include”jni.h”

在原始檔目錄下新建.cpp檔案,起名main.cpp。寫入程式:

#include "testNative.h"
#include "jni.h"//注意新增這句
#include<iostream>


using namespace std;

JNIEXPORT void JNICALL Java_testNative_sayHello(JNIEnv *env, jobject obj)
{
	cout << "Hello World!" << endl;
	cout << "I come from C++!" << endl;
}

另外,注意,在右側目錄中 右擊 解決方案-配置管理器

將Debug改成64位,因為我的IntelliJ idea是64位下的。這樣改動之後生成的dll可以用在64位平臺下。

之後按F5執行,執行成功如圖所示。

顯示生成的dll的路徑。找到此dll,複製。

4.將dll新增進JavaWEB工程中

將複製得到的dll改名為“hello.dll”,將其拷貝到JavaWeb專案目錄下,如圖所示:

之後執行專案,可以在控制檯輸出中看到如下圖所示結果,表示成功。

5.可能出現的錯誤

1.【注意事項】:如果你建的C++工程時32位的,當然Win32就是32位的工程,生成的dll只能執行在32位的JDK上。如果你的Java JDK64位的,那麼你新建Win32控制檯程式後,在專案屬性中修改平臺為64位即可。若不修改,出現如下錯誤:

2.第一次新建Win32控制檯選擇了預編譯表頭,如下圖所示:

在寫main.cpp時候執行出現如下錯誤:

注意不勾選 預編譯標頭。

3.【注意事項】testNative.h中的#include<jni.h>改為#include”jni.h”

寫在最後:新手起步,不斷學習總結。參考了網路資料,有問題提出大家共同交流!

轉載請註明出處,謝謝^_^