NDK是什么?
NDK(Native Development Kit)Android原生开发工具包,是一个包含API、交叉编译器、链接程序、调试器、构建工具、文档和示例应用程序的综合工具集。
为何要用到NDK?
- 代码保护,由于apk的java层代码很容易被反编译(即使混淆后),而C/C++库破解难度较大。
- 代码复用,在NDK中调用第三方C/C++库,因为大部分的开源库都是用C/C++代码编写的。
- 便于移植,用C/C++写的库可以方便在其他的嵌入式平台上再次使用。
Android NDK具体包含什么?
- ARM、x86和MIPS交叉编译器
- 构建系统
- Java原生接口头文件
- C库
- Math库
- POSIX线程
- 最小C++库
- ZLib压缩库
- 动态链接库
- Android日志库
- Android像素缓冲区
- Android原生应用APIs
- OpenGL ES 3D图形库
- OpenSL ES 原生音频库
- OpenMAX AL 最小支持
Android NDK工具介绍
ndk-build:编译Android动态链接库.so
ndk-gdb: GUN调试器相关
ndk-stack:原生层堆栈信息
Android NDK C++ Support
支持的C++运行库比较
C++运行库 | C++异常支持 | C++RTTI支持 | C++标准库 |
---|---|---|---|
system系统库 | No | No | No |
GAbi++ | No | Yes | No |
STLport | No | Yes | Yes |
GNU STL | Yes | Yes | Yes |
在Application.mk文件中控制使用
APP_STL := system
默认使用system,使用最多的设置是gnustl_static
C++异常的支持
不仅仅需要在Application.mk中配置APP_CPPFLAGS += -fexceptions
,还需要在Android.mk对应的module下添加LOCAL_CPP_FEATURES += exceptions
C++RTTI的支持
Run-Time Type Information运行库类型信息,是一种机制,用于执行安全类型转化。考虑兼容性和性能,默认不开启
LOCAL_CPP_FEATURES += rtti
APP_CPPFLAGS += -frtti
静态库与动态库的选择
静态库:项目仅包含单一的原生模块
动态库:项目包含多个原生模块
逆向加载库文件,先加载依赖库,然后才可以加载依赖于它的原生模块
C++标准库入门
容器
容器是一个对象,存放其他对象,提供访问操作元素的方法,并提供容器内对象的生命周期
序列
序列是大小可变的元素线性排序的容器
- vector支持随机访问元素,支持在末尾以常量时间插入和删除元素,在其他位置以线性时间插入和删除元素
- deque支持vector所有,并且支持序列起始位置以常量时间插入和删除元素
- list双向链表
- slist单向链表
关联容器
关联容器是一种大小可变的容器,支持通过键高效检索
- 排序关联容器
按区分大小写升序排序来存储键值,操作复杂度小于等于对数阶
set 元素不同,已排序
map 元素不同,键值对
multiset 元素允许相同,已排序
multimap 元素允许相同,一键对多值 - 哈希关联容器
基于哈希表实现,适合做快速查询,不排序
hashed_set 不允许重复元素
hash_map 键值对
hash_multiset 允许重复元素
hash_multimap 元素允许相同,一键对多值
适配器
容器适配器用于在已有的基本容器类型的基础上提供专门的容器类型
- stack 后进先出(LIFO)
- queue 先进先出(FIFO)
String
String字符序列同样为容器类型,除序列常用的方法外,string类追加了标准的字符串操作方法,如字符串串联和搜索
迭代器
迭代器可以对指定范围内或一个容器内的对象进行迭代。迭代器是泛化指针,但它们被实现成为通用类的形式。迭代器是容器之间的接口和算法,基于访问权限的级别和要执行的操作类型,分5种基本迭代器:
- Input iterator: 读取引用元素的值
- Output iterator: 修改当前位置对象的值
- Forward iterator: 不规定输入输出操作,用于符合值的线性序列的多种算法
- Bidirectional iterator: 向前或向后遍历给定范围元素
- Random access iterator: 提供普通C指针算法的所有操作
算法
对给定范围的元素,算法提供功能对其搜索、替换、复制和提取边界。依靠迭代器多位接口遍历容器
C++运行库线程安全
C++运行库的实现都是线程安全的,对共享容器的多线程读操作为线程安全,但读写同时操作需要保证互斥性
C++运行库调试模式
GNU STL调试模式
使用_gnu_debug
命名空间代替std
为容器提供调试模式启动副本,更优的选择使用预处理标识_GLIBCXX_DEBUG
在Android.mk文件中使用LOCAL_CFLAGS += -D_GLIBCXX_DEBUG
开启调试模式
STLport调试模式
预处理标识_STLP_DEBUG
在Android.mk文件中定义
LOCAL_CFLAGS += -D_STLP_DEBUG
LOCAL_CFLAGE += -D_STLP_DEBUG_MESSAGE
LOCAL_LDLIBS += -llog
实现全局函数__stl_debug_message
#include <stdarg.h>
#include <android/log.h>
void __stl_debug_message(const char* format_str, ...){
va_list ap;
va_start(ap, format_str);
__android_log_vprint(ANDROID_LOG_FATAL, "STLport", format_srt, ap);
va_end(ap);
}