安装 CMake、LLDB与NDK 开发工具包
CMake 简介
CMake
是一款比make
更强大的编译自动配置工具。
它可以根据不同平台、不同的编译器,并通过CMakeLists.txt
文件中简单的语句来描述所有平台的编译过程,生成相应的Makefile文件或project
文件。CMake被引入于AndroidStudio2.2
,其目的是替代原有的JNI/DNK
开发方法,使AS在进行JNI/NDK
时更加的方便、高效。
CMake的优势
- 允许直接在
C/C
代码中加入断点,调试; - 在Java层中使用“ctrl 左键”快捷键能够直接进入本地方法对应的
C/C
代码中; - 在
C/C
中使用“ctrl 鼠标点击”快捷键能够直接进入头文件或库; - 自动生成函数原型头文件,无需配置
android.useDeprecatedNdk=true
属性;
LLDB 简介
LLDB
是一个高效的C/C
调试器,它提供了丰富的流程控制和数据检测,有效地帮助我们调试程序。Android Studio通过引入LLDB
调试器,能够实现对NDK
本地代码的调试。
创建支持C/C 开发的Android工程
在Android studio 3.3中直接new一个Project,然后按照以下流程 操作 首先选择 Native C
在Customize C Support部分,可以使用下列选项自定义项目。
C Standard
:选择哪一种C 标准,默认选择Toolchain Default
选项,其会使用默认的Cmake配置;
工程结构解析
externalNativeBuild
文件夹:用于存放cmake
编译好的文件,包括支持的各种硬件等信息,有点类似于build.gradle
文件明确Gradle如何编译APP;cpp
文件夹:存放C/C
代码文件,native-lib.cpp
文件默认生成的;CMakeLists.txt
:cmake
脚本配置文件,cmake会根据该脚本文件中的指令去编译相关的C/C
源文件,并将编译后产物生成共享库或静态块,然后Gradle将其打包到APK中。
CMakeLists.txt
文件解析如下:
指定cmake版本cmake_minimum_required(VERSION 3.4.1)
add_library命令用于向cmake添加依赖库或者源文件 参数(函数名称,库类型,依赖源文件相对路径)
add_library(
# Sets the name of the library.
# 生成函数库的名称,即libnative-lib.so或libnative-lib.a(lib和.so/.a默认缺省) JNILearning
#生成库类型,动态库为SHARED 静态库为STATIC
# Sets the library as a shared library.
SHARED
#依赖 c/cpp相对路径
# Provides a relative path to your source file(s). JNILearning.cpp)
定位ndk中的库
find_library( # Sets the name of the path variable.
# 设置path变量的名称,这里为NDK中的日志库
log-lib
#指定cmake查询库的名称
#即在ndk开发包中查询liblog.so函数库,将其路径赋值给log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log)
指定想要关联的原生库
target_link_libraries( # Specifies the target library.
# 指定目标库,与上面指定的函数库名一致
JNILearning
# 链接的库,根据log-lib变量对应liblog.so函数库
# Links the target library to the log library
# included in the NDK.
${log-lib})
运行效果
通过查看native-lib.cpp
方法,stringFromJNI
目的是向Java层返回一个字符串。如果要在native-lib.cpp
文件中添加新的方法,必须添加在extern"C" { }
中,或者在每个方法前加extern"C"
, 否则会报找不到方法。如果源文件为C,则须将extern“C”
部分去掉,因为extern "C"
的作用就是告诉编译器以C方式编译。
extern "C" JNIEXPORT jstring JNICALL
/**
* CPP 源文件,返回一个字符串
* @param env
* @return
*/
Java_com_example_jnilearndemo_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello JNI";
return env->NewStringUTF(hello.c_str());
}
构建和运行APP流程:
Gradle
调用外部构建脚本CmakeLists.txt;
CMake
按照构建脚本中的命令将 C 源文件native-lib.cpp
编译到共享的对象库中,并命名为libnative-lib.so,Gradle
随后会将其打包到 APK 中;- 运行时,应用的
MainActivity
会使用System.loadLibrary()
加载原生库,至此,调用so中的方法才会生效。 最后运行图如下所示:
本地代码调试
第一次本地代码调试需要初始化一些工具需要一定时间,后面再调试就很快了
当使用Eclipse
进行NDK/JNI
开发时,基本无法对C/C 本地代码调试,而Android Studio却非常容易。AS通过借助LLDB
调试工具,可以非常方便地对C/C 本地代码进行调试。LLDB
调试的步骤基本与调试Java层代码一致,只是断点标志在C/C
函数中。
调试如下所示: