示例:hello-jni

此示例指导您完成 hello-jni,这是一个使用 NDK 构建的最小 C/C++ 应用。此示例位于 ndk-samples 代码库的 hello-jni 目录中,位于 android-mk 分支 内。

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 源代码中声明的本机函数相对应。jstring 返回类型是 Java 本机接口规范 (Java Native Interface Specification) 中定义的数据类型。它实际上不是字符串,而是指向 Java 字符串的指针。

jstring 之后是函数名,该函数名基于 Java 函数名和包含它的文件的路径。请按照以下规则构造它

  • 在其前面添加 Java_
  • 描述相对于顶级源目录的文件路径。
  • 使用下划线代替正斜杠。
  • 省略 .java 文件扩展名。
  • 在最后一个下划线之后,附加函数名。

按照这些规则,此示例使用函数名 Java_com_example_hellojni_HelloJni_stringFromJNI。此名称指的是名为 stringFromJNI() 的 Java 函数,该函数位于 hellojni/src/com/example/hellojni/HelloJni.java 中。

JNIEnv* 是指向 VM 的指针,jobject 是指向从 Java 端传递的隐式 this 对象的指针。

以下行调用 VM API (*env),并向其传递一个返回值:即 Java 端函数请求的字符串。

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