範例:hello-jni

這個範例會引導您使用 NDK 建構小型 C/C++ 應用程式 hello-jni。您可以在 android-mk 分支版本中 ndk-samples 存放區的 hello-jni 目錄找到這個範例。

Android.mk

以下兩行程式碼提供原生來源檔案的名稱,以及要建構的共用程式庫名稱。建構系統新增 lib 前置字串和 .so 副檔名之後,建構程式庫的全名會是 libhello-jni.so

LOCAL_SRC_FILES := hello-jni.c
LOCAL_MODULE    := hello-jni

如要進一步瞭解 Android.mk 檔案的用途和使用方法,請參閱 Android.mk

Application.mk

這行程式碼會指示建構系統要針對哪個 CPU 和架構進行建構。在這個範例中,建構系統會針對所有支援的架構進行建構。

APP_ABI := all

如要進一步瞭解 Application.mk 檔案及其使用方法,請參閱 Application.mk

Java 端實作

helloJNI.java 檔案位於 hellojni/src/com/example/hellojni/ 中。這個檔案會呼叫函式從原生端擷取字串,然後在螢幕上顯示該字串。

原始碼包含 NDK 使用者應特別留意的三行程式碼。 下文將以使用順序 (而非編寫的順序) 展示這三行程式碼。

應用程式啟動時,這項函式呼叫便會載入 .so 檔案。

Kotlin

System.loadLibrary("hello-jni")

Java

System.loadLibrary("hello-jni");

在這個方法宣告中,native 關鍵字的作用是告知虛擬機器函式位於共用程式庫中 (亦即已在原生端實作)。

Kotlin

external fun stringFromJNI(): String

Java

public native String stringFromJNI();

Android 架構會呼叫上述步驟中載入及宣告的函式,並在螢幕上顯示字串。

Kotlin

tv.text = stringFromJNI()

Java

tv.setText( stringFromJNI() );

C 端實作

hello-jni.c 檔案位於 hello-jni/jni/ 中,其中包含的函式會傳回 Java 端要求的字串。函式宣告如下:

JNIEXPORT jstring JNICALL
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                                  jobject thiz )

這個宣告與 Java 原始碼中宣告的原生函式對應。傳回類型 jstringJava 原生介面規範中定義的資料類型,它是 Java 字串的指標,並非真正的字串。

傳回 jstring 後,接著是根據 Java 函式名稱和這個函式所在檔案的路徑傳回的函式名稱。請根據下列規則設定函式名稱:

  • 在開頭加上 Java_
  • 說明與頂層來源目錄相關的檔案路徑。
  • 以底線取代正斜線。
  • 刪除 .java 副檔名。
  • 在最後一個底線後面加上函式名稱。

依據這些規則,這個範例使用的函式名稱是 Java_com_example_hellojni_HelloJni_stringFromJNI。這個名稱指的是 hellojni/src/com/example/hellojni/HelloJni.java 中一個名為 stringFromJNI() 的 Java 函式。

JNIEnv* 是 VM 的指標,而 jobject 是從 Java 端傳遞的隱含 this 物件的指標。

以下這行程式碼會呼叫 VM API (*env),並向其傳遞傳回值 (亦即 Java 端函式要求的字串)。

return (*env)->NewStringUTF(env, "Hello from JNI !
Compiled with ABI " ABI ".");