Android NDK開發(fā)(一)JNI簡介及調(diào)用流程

轉(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ù)更新!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容