轉(zhuǎn)載:http://blog.csdn.net/u011974987/article/details/52602913
前言
前段時間學(xué)習(xí)了C、C++的一些基礎(chǔ)知識后,了解了它們的編碼風(fēng)格,要想掌握NDK開發(fā),前提是會使用JNI,下面我們開始簡單的介紹吧!
JNI簡介
JNI全稱是Java Native Interface(Java本地接口),本地接口就是指用C和C++開發(fā)的接口。從Java1.1開始,JNI標準成為java平臺的一部分,它允許Java代碼和其他語言寫的代碼進行交互。JNI一開始是為了本地已編譯語言,尤其是C和C++而設(shè)計的,但是它并不妨礙你使用其他編程語言,只要調(diào)用約定受支持就可以了。
開發(fā)JNI程序會受到系統(tǒng)環(huán)境的限制,因為用C/C++語言寫出來的代碼或模塊,編譯過程當中要依賴當前操作系統(tǒng)環(huán)境所提供的一些庫函數(shù),并和本地庫鏈接在一起。而且編譯后生成的二進制代碼只能在本地操作系統(tǒng)環(huán)境下運行,因為不同的操作系統(tǒng)環(huán)境,有自己的本地庫和CPU指令集,而且各個平臺對標準C/C++的規(guī)范和標準庫函數(shù)實現(xiàn)方式也有所區(qū)別。這就造成使用了JNI接口的JAVA程序,不再像以前那樣自由的跨平臺。如果要實現(xiàn)跨平臺,就必須將本地代碼在不同的操作系統(tǒng)平臺下編譯出相應(yīng)的動態(tài)庫。
JNI的開發(fā)流程主要分為以下幾個步驟:
編寫帶有native聲明方法的java類;
用”javac”命令來編譯所編寫的java類;
使用”javah”java類的名生成擴展名為h的頭文件;
復(fù)制jni.h和jni_md.h文件到CPP工程中;
實現(xiàn).h頭文件中聲明的函數(shù)
生成dll動態(tài)鏈接庫
配置dll文件所在目錄到環(huán)境變量
重啟Eclipse
jni調(diào)用dill的流程圖如下:

通過上面的分析,相信大家已經(jīng)對jni的開發(fā)流程有一個整體的認識,接下來,我們將通過實例更進一步的了解。
第一步:編寫帶有native聲明方法的java類
JniTest.java
package com.study.jni;
public class JniTest {
????public native static String getStringFromC();
}
第二步:用”javac”命令來編譯所編寫的java類;
首先我們必須得配有java環(huán)境變量,然后我們右鍵點擊項目->properties,復(fù)制項目路徑;

然后進入dos命令,
C:\Users\uuxuh>cd E:\Documents\11\JniTest
C:\Users\uuxuh>E:
E:\Documents\11\JniTest>cd src
E:\Documents\11\JniTest\src>
第三步:使用”javah”java類的名生成.h的頭文件
接著,復(fù)制我們的完整類名(包名+類名),執(zhí)行命令:
E:\Documents\11\JniTest\src>javah com.study.jni.JniTest
回到工程目錄下,刷新項目,編譯后的.h頭文件就出現(xiàn)了。
源碼:
com_study_jni_JniTest.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class com_study_jni_JniTest */
#ifndef _Included_com_study_jni_JniTest
#define _Included_com_study_jni_JniTest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_study_jni_JniTest
* Method: getStringFromC
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_study_jni_JniTest_getStringFromC (JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
第四步:復(fù)制jni.h和jni_md.h文件到CPP工程中
將要編譯的文件中引入了
#inlcude
頭文件,所以我們手動導(dǎo)入這兩個文件到CPP工程中,
以我的jdk1.7.0_75為例,兩個頭文件的位置分別為:
jni.h jdk1.7.0_75/include
jni_md.h jdk1.7.0_75/include/linux
將我們生成.h頭文件復(fù)制到項目的代碼文件目錄下 , 在解決方案中的頭文件目錄-> 右鍵-> 添加 -> 添加現(xiàn)有項 。 將我們的頭文件添加進來,還有jni.h和jni_md.h一起添加進來,如圖:

第五步:實現(xiàn).h頭文件中聲明的函數(shù)
c代碼如下:
#include "com_study_jni_JniTest.h"
//函數(shù)實現(xiàn)
JNIEXPORT jstring JNICALL Java_com_study_jni_JniTest_getStringFromC (JNIEnv *env, jclass jcls){
//簡單的實現(xiàn)
????return (*env)->NewStringUTF(env, "C String");
}
第六步:生成dll動態(tài)鏈接庫
我們以VS2013為例:
操作步驟:
選中項目 -> 右鍵 -> 屬性 -> 常規(guī) -> 項目默認值 -> 配置類型 , 選擇動態(tài)庫.dll,

如圖,右上角配置管理器,根據(jù)我們所使用的平臺進去配置一下:

這里我使用64位的,所以活動解決方案平臺下新建了一個x64,部署項目配置也選擇x64。
配置完了之后,最后生成解決方案。去項目目錄下查看dll動態(tài)庫。

第七步:配置dll文件所在目錄到環(huán)境變量
我們把生成dll文件的路徑配置java環(huán)境變量里面,這樣java 才會知道有dll動態(tài)庫存在,配置完之后,重啟下Eclipse。
最后我們在java中調(diào)用動態(tài)庫,完整代碼:
package com.study.jni;
public class JniTest {
????public native static String getStringFromC();
????public static void main(String[] args) {
????????System.out.println(getStringFromC());
????}
????// 加載動態(tài)庫
????static{
????????System.loadLibrary("jni_study");
????}
}
最后運行一下項目控制臺打印出C中返回給我們的字符串。

好了,整個jni的調(diào)用流程已經(jīng)說的非常詳細了,但這只是jni入門的基礎(chǔ),后續(xù)會繼續(xù)更新!