0%

在 Android Sudio 中使用 JNI

target_link_libraries 是 CMake 中用于将共享库或静态库链接到目标可执行文件或共享库的命令。

1
2
// 其中,<target> 是要链接库的目标文件的名称,item1、item2 等是要链接到目标文件的库的名称。
target_link_libraries(<target> [item1] [item2] [...])

example:

1
2
add_library(mylib SHARED mylib.cpp)
target_link_libraries(myexe mylib)
1
2
3
add_library(mylib1 SHARED mylib1.cpp)
add_library(mylib2 SHARED mylib2.cpp)
target_link_libraries(mylib2 mylib1)

上述代码将创建两个共享库 mylib1 和 mylib2,并将 mylib1 链接到 mylib2 中。这意味着,在链接 mylib2 时,CMake 将自动链接 mylib1。

AS 中 so 文件的生成位置

\app\build\intermediates\cmake\debug\obj

module build.gradle setting

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
defaultConfig {
...

externalNativeBuild {
cmake {
cppFlags "-std=c++11"
abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
}
}

ndk {
abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
}
}

externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}

CMakeLists.txt example

1
2
3
4
5
6
7
8
cmake_minimum_required(VERSION 3.4.1)

add_library(fibonacci SHARED
jni/fibonacci.cpp) // fibonacci.cpp is located under /app/jni/fibonacci.cpp

find_library(log-lib log)

target_link_libraries(fibonacci ${log-lib})

located under folder /app

add multi cpp files

1
2
3
4
5
6
7
8
9
10
add_library( # Specifies the name of the library.
native-lib

# Sets the library as a shared library.
// 此处使用 SHARED 标志将库设置为共享库。如果需要将库设置为静态库,则应使用 STATIC 标志。
SHARED

# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp
src/main/cpp/another-file.cpp )

comment for a piece of code

1
2
3
4
5
6
7
8
9
10
11
// extern "C":C++ 中的一个关键字,用来指定函数使用 C 语言的命名和调用约定。在 JNI 中使用 C 的命名和调用约定非常重要,因为 Java 虚拟机只能通过 C 调用本地函数。因此,需要将 C++ 代码中的函数标记为 C 语言的函数,以便能够正确地被 Java 虚拟机调用。
// JNIEXPORT:JNI 中的宏,用来指定函数的可见性和调用约定。JNIEXPORT 宏被定义为 C 语言的 extern,用于声明一个导出函数
// JNICALL:JNI 中的宏,用来指定函数的调用约定。在 Windows 上,函数的调用约定为 __stdcall,而在其他操作系统上,函数的调用约定为默认的 C 语言调用约定。
extern "C" JNIEXPORT jint JNICALL
// Java_com_cmder_jnitest_MainActivity_calculateFibonacci:JNI 函数的名称,其中 Java_ 是 JNI 的命名约定,com_cmder_jnitest_MainActivity 是 Java 类的全限定名,calculateFibonacci 是 Java 方法的名称
// JNIEnv* env:JNI 函数的参数,表示指向 JNI 环境的指针。JNI 环境是一个结构体,包含了许多函数指针,用于操作 Java 对象和调用 Java 方法。
// jobject thiz:JNI 函数的参数,表示调用本地函数的 Java 对象的引用。在本例中,它是 MainActivity 类的一个实例。
// jint n:JNI 函数的参数,表示一个 Java int 类型的整数,它将传递给 C/C++ 代码。
Java_com_cmder_jnitest_MainActivity_calculateFibonacci(JNIEnv* env, jobject thiz, jint n) {
return fibonacci(n);
}

add so files in Android Studio

1
2
3
4
5
6
7
8
9
10
11
android {
// ...
sourceSets {
main {
// 4 so files, auto adapt
jniLibs.srcDirs = ['src/main/jniLibs']
// or
jniLibs.srcDirs = ['libs']
}
}
}