白乐天

道阻且长,行则将至。

ndk开发

介绍

NDK(Native Development Kit)

Android NDK 是一个工具集,可以使用 C 和 C++ 等语言以原生代码实现应用的各个部分。
NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk。

JNI(Java Native Interface)

从Java1.1开始,jni标准成为Java平台的一部分,允许Java代码和其他语言写的代码进行交互。
NDK是开发套件,JNI才是调用的框架。JNI是Java调用Native 语言的一种特性。通过JNI可以使得Java与C/C++机型交互。

ndk中的Log输出

1
2
3
4
5
6
7
8
9
10
#include <android/log.h>

#define LOG_TAG "MyApp" // 设置日志标签

int __android_log_print(int priority, const char *tag, const char *fmt, ...);

// priority: 日志的优先级(日志级别),决定日志的严重性。
// tag: 日志标签,用于标识日志来源。通常是应用的名称或功能模块。
// fmt: 格式化字符串,类似于 C 标准库中的 printf 格式。
// ...: 可选的附加参数,用于格式化字符串的内容。

示例

1
2
3
4
5
6
7
8
9
10
11
12
#include <android/log.h>

#define LOG_TAG "MyNDKApp"

void logExample() {
__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "This is a VERBOSE log");
__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "This is a DEBUG log");
__android_log_print(ANDROID_LOG_INFO, LOG_TAG, "This is an INFO log");
__android_log_print(ANDROID_LOG_WARN, LOG_TAG, "This is a WARN log");
__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "This is an ERROR log");
__android_log_print(ANDROID_LOG_FATAL, LOG_TAG, "This is a FATAL log");
}

ndk初始化函数与构造函数

_init 函数

_init 函数与程序初始化有关。它会在动态库被加载时自动调用,通常用于执行一些初始化操作。

1
2
3
extern "C" void _init() {

}

attribute((constructor))构造函数

指定函数为构造函数,使得它们在程序或动态库加载时自动执行。

1
2
3
__attribute__ ((constructor)) void init_function1() {
__android_log_print(ANDROID_LOG_DEBUG, "initTest", "This is a init_function1 log");
}

设置优先级

当定义多个构造函数时,它们会按优先级顺序执行。如果没有显式指定优先级,则按声明顺序执行。优先级越低的构造函数会先执行,数字越高,执行顺序越靠后。

1
2
3
4
5
6
7
__attribute__ ((constructor(300))) void init_function2(){
__android_log_print(ANDROID_LOG_DEBUG, "initTest", "This is a init_function2 log");
}

__attribute__ ((constructor(200))) void init_function3(){
__android_log_print(ANDROID_LOG_DEBUG, "initTest", "This is a init_function3 log");
}

隐藏函数符号

1
2
3
__attribute__ ((constructor, visibility("hidden"))) void init_function4() {
__android_log_print(ANDROID_LOG_DEBUG, "initTest", "This is a init_function4 log");
}

demo测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
extern "C" void _init(){
__android_log_print(ANDROID_LOG_DEBUG, "initTest", "This is a _init log");
}

__attribute__ ((constructor)) void init_function1(){
__android_log_print(ANDROID_LOG_DEBUG, "initTest", "This is a init_function1 log");
}

__attribute__ ((constructor(300))) void init_function2(){
__android_log_print(ANDROID_LOG_DEBUG, "initTest", "This is a init_function2 log");
}

__attribute__ ((constructor(200))) void init_function3(){
__android_log_print(ANDROID_LOG_DEBUG, "initTest", "This is a init_function3 log");
}

__attribute__ ((constructor, visibility("hidden"))) void init_function4(){
__android_log_print(ANDROID_LOG_DEBUG, "initTest", "This is a init_function4 log");
}

输出日志

_init函数是最先执行的函数,然后按照构造函数的优先级顺序执行。

反汇编分析

__init函数经过反编译得到了.init_proc函数

构造函数出现在.init_array段里

函数执行顺序

1
2
3
4
_init
constructor
JNI_Onload
其他函数