Android的JNI調用,AndroidJNI調用

來源:互聯網
上載者:User

Android的JNI調用,AndroidJNI調用

  Android提供NDK開發包來提供Android平台的C++開發,用來擴充Android SDK的功能。主要包括Android NDK構建系統和JNI實現與原生代碼通訊兩部分。

一、Android NDK構建系統

  Android NDK的構建系統是基於GNU Make的。Android GNU Make系統除了需要一些內部的GNU片段外,還需要兩個檔案:Android.mk和Application.mk。Android NDK源碼給了很多的例子,以HelloJni為例,Android.mk源碼: 

#Android.mk必須以LOCAL_PATH變數開頭
LOCAL_PATH := $(call my-dir)#清除除了LOCAL_PATH以外的LOCAL_<name>變數,例如LOCAL_MODULE與LOCAL_SRC_FILES等include $(CLEAR_VARS)#每一個原生組件被稱為一個模組LOCAL_MODULE := hello-jni
#源檔案LOCAL_SRC_FILES := hello-jni.c#編譯為共用庫,即尾碼名為.soinclude $(BUILD_SHARED_LIBRARY)

  Application.mk源碼: 

 APP_ABI := all

  一般選擇APP_ABI := armeabi-v7a就夠了

  為了建立可供主應用程式使用的模組,必須將該模組變成共用庫。按照上述必不可少的步驟,可以繼續編譯多個共用庫。

  Android也可以編譯靜態庫(尾碼名為.a),但是實際的Android應用程式並不直接使用靜態庫,並且應用程式套件組合中也不包含靜態庫。靜態庫可以用來構建共用庫。但是,當靜態庫與多個共用庫相連時,應用程式套件組合中會包含靜態庫的多個副本,徒增應用程式套件組合的大小。這種情況下,可以不構建靜態庫,而是將通用模組作為共用庫建立起來,動態串連相依模組以消除重複的副本。

……

……

……

Prebuilt庫

共用模組編譯時間要求有原始碼,為此Android提供了Prebuilt庫,以下場合,Prebuilt庫是非常有用的:

其他構建系統變數:

LOCAL_CFLAGS:一組可選的編譯器標誌,在編譯C和C++源檔案的時候會被傳送給編譯器;

LOCAL_CPP_FLAGS:一組可選的編譯器標誌,在只編譯C++源檔案時被傳送給編譯器;

LOCAL_LDLIBS:連結標誌的可選列表,它主要用於傳送要進行動態連結的系統庫列表。如連結日誌庫:

LOCAL_LDFLAGS += -llog 

APP_CPPFLAGS:編譯器標誌,在編譯任何模組的C++源檔案時這些標誌都會被傳送給編譯器。 

  nkd-build指令碼命令:

ndk-build –C /project pathndk-build –Bndk-build clean 
二、JNI實現與原生代碼通訊2.1 C/C++ 標頭檔產生器:javah

  JDK內建一個名為javah的命令列工具,該工具由Java類檔案的原始定義產生原生函數名及其參數列表。C/C++源檔案只需要包含這個標頭檔並提供原生方法實現。 

  Javah的參數列表如下: 

C:\Users\jiayayao>javah用法:  javah [options] <classes>其中, [options] 包括:  -o <file>                輸出檔案 (只能使用 -d 或 -o 之一)  -d <dir>                 輸出目錄  -v  -verbose             啟用詳細輸出  -h  --help  -?           輸出此訊息  -version                 輸出版本資訊  -jni                     產生 JNI 樣式的標題檔案 (預設值)  -force                   始終寫入輸出檔案  -classpath <path>        從中載入類的路徑  -cp <path>               從中載入類的路徑  -bootclasspath <path>    從中載入引導類的路徑<classes> 是使用其全限定名稱指定的(例如, java.lang.Object)。

  產生標頭檔的命令列參數如下:

   javah -classpath bin/classes com.example.hellojni.Hellojni

  Java方法stringFromJNI不帶任何參數,但是原生方法帶兩個參數:

 

  這裡注意C與C++代碼稍有不同,C代碼如下:

  return (*env)->NewStringUTF(env, "Hello from JNI ! ");

  C++代碼如下:

  return env->NewStringUTF("Hello from JNI ! ");

  這是因為C++代碼中,JNIEnv實際上是一個C++類執行個體,JNI函數以成員函數的形式存在,因此JNI方法調用不要求JNIEnv執行個體作參數。   

2.2 資料類型

Java有兩種資料類型:基礎資料型別 (Elementary Data Type)和引用資料類型:基礎資料型別 (Elementary Data Type)中Java/JNI/C++的映射關係如下:

 

參考型別的類型映射關係如下:

 

參考型別以不透明的引用方式傳遞給原生代碼,而不是以原生資料類型的的形式呈現,因此參考型別不能直接使用和修改。JNI提供了與這些參考型別密切相關的一組API。

Get<Type>ArrayRegion函數將給定的基本Java數組複製到給定的C數組中,如程式: 

從C數組向Java數組提交所作的修改,如程式:

 

原生方法的記憶體配置超出了虛擬機器的管理範圍,且不能用虛擬機器的記憶體回收行程回收原生方法中的記憶體。

原生代碼回到Java損耗效能,建議將所有需要的參數傳遞給原生代碼調用,而不是讓原生代碼回到Java中。

 

 

GetStringUTFChars

ReleaseStringUTFChars

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.