今天開始第一天學習jni編程,帶著好奇和恐懼的心理去學習。
首先我們先來了解一下什么是JNI,什么是NDK。
JNI(Java Native Interface)
java虛擬機的一部分,允許java代碼和其他語言代碼進行交互。jni是一個協(xié)議,通常用來溝通java與c/c++,通俗的來說就是java世界與c/c++世界溝通的橋梁。
什么時候使用JNI呢?
- java api不能滿足我們程序的需求時候。
- 圖像渲染,算法計算,效率要求非常高的情況下。
- 需要訪問一些已有的本地庫。
JNI開發(fā)步驟
(使用Eclipse還有vs2013)
- Eclipse下編寫 native方法。
- 用javah命令,生成.h文件。
- 復制.h頭文件到vs的項目工程中。
- 復制jni.h和jni_md.h到vs下
- 實現(xiàn).h頭文件中的聲明函數(shù)
- 生成一個dll動態(tài)庫
- 在java中加載動態(tài)庫
- 觸發(fā)native函數(shù)
好了大概步驟就如上述所示,下面就開始按照上述步驟敲代碼了。
編寫native方法
package com.jni.demo;
public class JniMain {
/**
* native方法
* @return
*/
public native static String getDataFromC();
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
執(zhí)行javah命令生成.h文件
找到自己eclipse項目的路徑,到src目錄。

好,這個時候刷新一下項目,就會多了一個com_jni_demo_JniMain.h文件。
然后將此.h文件復制到vs工程的目錄下。

回到vs工程,右擊頭文件文件夾,添加→ 現(xiàn)有項→選中剛剛的.h文件。
ok此時成功將eclipse生成的.h文件加入到vs項目中

復制jni.h和jni_md.h到vs下解決頭文件錯誤
有沒有發(fā)現(xiàn)上圖的這個頭文件好像很多錯誤,難道生成有問題么?
好的著手這些預編譯問題。
首先我們先去jdk目錄找本人目錄是(C:\Program Files\Java\jdk1.8.0_60),搜索一下,找到了jni.h和jni_md.h。
然后復制到vs項目目錄下,右擊頭文件文件夾,添加→ 現(xiàn)有項→選中剛剛的.h文件。怎么回事,頭文件都加進去了還是報錯,因為這里jni.h不是系統(tǒng)的,所以要把尖括號改成雙引號,#include <jni.h> →#include "jni.h"
再瞧瞧jni.h發(fā)現(xiàn)也有錯誤,缺少jni_md.h,好了,這里一樣的操作,把jni_md.h引入進來。ok~解決了所有報錯問題了。
關(guān)鍵步驟,實現(xiàn)頭文件的聲明函數(shù)
這里,我們以c為列子,干掉cpp文件,添加一個.c文件。
復制com_jni_demo_JniMain.h中聲明函數(shù)到.c文件,對函數(shù)進行實現(xiàn)。這里函數(shù)實現(xiàn)一個簡單的輸出。
#include "stdafx.h" //預處理命令
#include "com_jni_demo_JniMain.h"
JNIEXPORT jstring JNICALL Java_com_jni_demo_JniMain_getDataFromC
(JNIEnv * env, jclass jcla){
char * ch= "Hello JNI!";
return (*env)->NewStringUTF(env, ch);
}
生成動態(tài)dll庫
首先點擊
選擇64位平臺運行。

而后選擇

好,現(xiàn)在點擊左上角,生成 → 生成解決方案。(有些同學這里會出現(xiàn)下面的錯)

解決方法:

改成不適用預編譯頭就ok了。
加載動態(tài)庫
好的接下來我們找到剛剛生成的dll,并把他copy到eclipse項目目錄下。
接下來通過下面代碼加載動態(tài)庫:
JniMain.java類
static {
System.loadLibrary("Jni_Demo");
}
loadLibrary的名字就是取得是dll名字。
觸發(fā)native函數(shù)
這里我執(zhí)行一個簡單的輸出語句
JniMain.java類
public static void main(String[] args) {
// TODO Auto-generated method stub
//觸發(fā)
System.out.println(getDataFromC());
}
yeah,執(zhí)行成功!

好的,就是這么容易的上手了,步驟記得好,擼碼沒煩惱。