Learning Android 第十五章 NDK 翻譯二

來源:互聯網
上載者:User
JNI標頭檔
下一個步驟就是在Fiblib Java檔案的基礎上建立C的標頭檔。如何做到呢,我們用Java的標準javah工具。前提是你要安裝上Java開發工具集(JDK),你會在JDK/bin目錄下找到這個工具。現在讓我們來建立C的標頭檔吧,去你的項目的bin目錄執行:
[Fibonacci/bin]> javah -jni com.marakana.FibLib
javah-jni 把一個Java類作為參數。並不是所有的類都預設在類路徑,所以很容易改變目錄為你項目的bin目錄。到這裡我們假設當前工作目錄為Java類路徑並且javah -jni com.marakana.FibLib能夠工作。
結果應該是產生一個名為com_marakana_FibLib.h的新檔案。這就是我們需要實現下一步的C標頭檔。在實現我們的本地檔案之前,讓我們管理我們的項目一小下。雖然Eclipse幫我們做了很多事,如安裝Android應用程式目錄等,但它並沒有提供很進階別和自動化的支援給NDK開發人員。我們接下來將要手動做兩個步驟。
第一步,在你的Eclipse中Fibonacci項目中建立一個名為jni的目錄,這裡就是用來存放所有你的本地代碼和相關檔案的地方。在Eclipse的Package Explorer中選擇Fibonacci項目,滑鼠右鍵選擇New->Folder,這樣就建立了目錄了。
第二步,把新的標頭檔放進這個檔案夾。命令為:
[Fibonacci/bin]> mv com_marakana_FibLib.h ../jni/

下面我們來看看這個檔案:

/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_marakana_FibLib */#ifndef _Included_com_marakana_FibLib#define _Included_com_marakana_FibLib#ifdef __cplusplusextern "C" {#endif/** Class: com_marakana_FibLib* Method: fibN* Signature: (I)J*/JNIEXPORT jlong JNICALL Java_com_marakana_FibLib_fibN(JNIEnv *, jclass, jint);/** Class: com_marakana_FibLib* Method: fibNI* Signature: (I)J*/JNIEXPORT jlong JNICALL Java_com_marakana_FibLib_fibNI(JNIEnv *, jclass, jint);#ifdef __cplusplus}#endif#endif

可以看到,這個檔案時自動產生的,並不需要程式員直接修改。這裡你還會觀察到我們已經實現的兩個本地函數的簽名。
...
JNIEXPORT jlong JNICALL Java_com_marakana_FibLib_fibN
(JNIEnv *, jclass, jlong);
...
JNIEXPORT jlong JNICALL Java_com_marakana_FibLib_fibNI
(JNIEnv *, jclass, jlong);
...

這些是標準的JNI簽名。上述兩個本地函數fibN和fibNI是按照命名規範(naming convention)並通過Java中的類com.marakana.FibLib包含的函數自動產生的。還可以看到這兩個函數都返回jlong,一個JNI標準的整型。
它們的輸入參數也很有意思:JNIEnv, jclass, 和 jlong。前兩個參數通常是Java類的部分,為本地代碼建立介面。JNIEnv是虛擬機器環境的指標。第二個參數是指向函數所在的類或對象,jclass是類方法,jobject是執行個體方法。第三個參數jlong,是我們輸入斐波那契演算法的那個數,也就是我們的n。
我們已經有了這個標頭檔,是時候提供它的C語言實現了。

C語言實現
我們將要建立一個C檔案用來實現我們的本地演算法。為簡單起見(for simplicity),我們把它起名為fib.c。像之前的標頭檔一樣,它也放在jni的檔案夾裡。用滑鼠右鍵點擊jni檔案夾,選擇New->File來建立它,儲存為fib.c。
注意:
當你開啟C語言檔案的時候可能會出現在Eclipse的外面用其他編輯器開啟檔案的情況。這是因為Java版的Eclipse預設是不支援C語言開發的。你可以用C語言開發工具擴充你的Eclipse,開啟Eclipse,Help->Install New Software。或者,就直接用檔案右鍵選擇文字編輯器中選擇標準的Eclipse文字編輯器(standard Eclipse text editor)開啟。

接下來,我們提供C語言的斐波那契演算法實現,請看Example15-2 。這個C語言版本幾乎和Java版本是一樣的(identical to)。
Example 15-2. jni/fib.c

#include "com_marakana_FibLib.h" /*(注釋一)*//* 遞迴斐波那契演算法(注釋二)*/long fibN(long n) {if(n<=0) return 0;if(n==1) return 1;return fibN(n-1) + fibN(n-2);}/*迭代斐波那契演算法(注釋三)*/long fibNI(long n) {long previous = -1;long result = 1;long i=0;int sum=0;for (i = 0; i <= n; i++) {sum = result + previous;previous = result;result = sum;}return result;}/*標頭檔中生產的JNI方法的簽名(注釋四)*/JNIEXPORT jlong JNICALL Java_com_marakana_FibLib_fibN(JNIEnv *env, jclass obj, jlong n) {return fibN(n);}/*標頭檔中生產的JNI方法的簽名(注釋五) */JNIEXPORT jlong JNICALL Java_com_marakana_FibLib_fibNI(JNIEnv *env, jclass obj, jlong n) {return fibNI(n);}

注釋一:我們引入com_marakana_FibLib.h,這個標頭檔是我們調用javah -jni com.marakana.FibLib產生的。
注釋二:實際的遞迴斐波那契演算法。這個與Java版本非常相似。
注釋三:迭代版的斐波那契,怎麼樣,又和Java版的很像吧。
注釋四:這是JNI為我們提供的函數。從com_marakana_FibLib.h複製粘貼的原型,增加了變數名並調用相應的C語言函數來做成了這樣子。
注釋五:同樣的,這是迭代方法的簽名。
現在我們就把C語言版的斐波那契實現了,我們將要構建成共用庫。那麼,我們就需要一個合適的makefile。

Makefile
為了構建本地庫,Android.mk makefile 必須要描述我們的檔案。請看Example 15-3 。
Example 15-3. jni/Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := fib
LOCAL_SRC_FILES := fib.c
include $(BUILD_SHARED_LIBRARY)

makefile是標準Android make系統的一部分。所有我們添加的檔案,是指定的輸入檔案(fib.c)和指定的輸出檔案(fib模組)。我們指定的模組的名稱很重要,它將會決定以作業系統約定為基礎的庫的名稱。舉個例子,在基於ARM的系統,輸出是libfib.so檔案。
一旦我們有了這個makefile,我們就做好了構建初始化的準備了。

構建共用庫
假定你已經安裝好了NDK,那你就可以運行ndk-build在你的項目路徑來構建本地共用庫了。這裡的ndk-build是一個工具,在你的NDK安裝目錄就可以找到它。我們假定你已經把這個目錄寫進了環境變數路徑。
這時候(at this point),你可能已經有了一個名為lib的子目錄包含了你的共用庫。當你在下一部分配置斐波那契應用的時候,這個庫會被打包成APK的一部分。

注意:
這個共用庫編譯後預設運行在模擬器上,所以它是基於ARM架構的。

最後,我們需要一個應用程式來使用這個庫。

斐波那契Activity
這個activity用來詢問使用者輸入一個數字,然後就計算這個數的四種斐波那契值。而且在螢幕上列印出計算時間和結果。這個activity基本上使用FibLib類繼而本地部分轉向使用libfib.so。看Example 15-4的代碼。

Example 15-4. FibActivity.java

package com.marakana;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;public class Fibonacci extends Activity implements OnClickListener {TextView textResult;Button buttonGo;EditText editInput;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);// Find UI viewseditInput = (EditText) findViewById(R.id.editInput);textResult = (TextView) findViewById(R.id.textResult);buttonGo = (Button) findViewById(R.id.buttonGo);buttonGo.setOnClickListener(this);}public void onClick(View view) {int input = Integer.parseInt(editInput.getText().toString()); //注釋一long start, stop;long result;String out = "";// Dalvik - Recursivestart = System.currentTimeMillis(); //注釋二result = FibLib.fibJ(input); //注釋三stop = System.currentTimeMillis(); //注釋四out += String.format("Dalvik recur sive: %d (%d msec)", result,stop - start);// Dalvik – Iterativestart = System.currentTimeMillis();result = FibLib.fibJI(input); //注釋五stop = System.currentTimeMillis();out += String.format("\nDalvik iterative: %d (%d msec)", result,stop - start);// Native - Recursivestart = System.currentTimeMillis();result = FibLib.fibN(input); //注釋六stop = System.currentTimeMillis();out += String.format("\nNative recursive: %d (%d msec)", result,stop - start);// Native - Iterativestart = System.currentTimeMillis();result = FibLib.fibNI(input); //注釋七stop = System.currentTimeMillis();out += String.format("\nNative iterative: %d (%d msec)", result,stop - start);textResult.setText(out); //注釋八}}

注釋一:將使用者輸入的字串轉換為整形。
注釋二:在開始計算之前,擷取當前的時間戳記(timestamp)。
注釋三:我們在FibLib中調用相關的靜態函數來顯示實際的斐波那契計算。這裡是Java遞迴實現。
注釋四:擷取另一個時間戳記並減(subtract)前一個。結果就是計算的時間,單位是毫秒(milliseconds)。
注釋五:Java的迭代實現。
注釋六:本地遞迴演算法。
注釋七:最後,調用本地迭代演算法。

注釋八:格式化輸出並列印在螢幕上。

linc註:

把ndk-build寫到環境變數:

用文字編輯器開啟/etc/profile
在profile檔案末尾加入:

NDK=/home/linc/android/android-ndk-r5bexport NDKPATH=$NDK:$PATHexport PATH

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.