初探CMake开发NDK

2018-01-18 11:01:04来源:https://www.jowanxu.top/2018/01/16/Android_CMake_NDK/作者:旺仔的个人博客人点击

分享

使用CMake来进行NDK开发。


事前准备

打开Android Studio->Setting->Android SDK,下载安装CMake、LLDB、NDK。



在新建项目的时候默认会配置好所有的环境,如果是旧的项目需要以下准备:


在gradle.properties文件中添加对过时的NDK的兼容使用


android.useDeprecatedNdk=true

在模块的 build.gradle 里面添加


android {
defaultConfig {
externalNativeBuild {
cmake {
cppFlags ""
}
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}

CMakeLists文件


CMakeLists.txt是CMake的配置文件,用于表明版本、依赖、等信息,文件位置在 app/CMakeLists.txt 。


# 设置构建本地库所需的最小版本的cbuild。
cmake_minimum_required(VERSION 3.4.1)
# 创建并命名一个库,将其设置为静态
#或者共享,并提供其源代码的相对路径。
# 您可以定义多个库,而cbuild为您构建它们。
#Gradle自动将共享库与你的APK打包。
add_library( hello-lib#设置库的名称。即SO文件的名称,生产的so文件为“libhello-lib.so”,在加载的时候“System.loadLibrary("hello-lib");”
SHARED# 将库设置为共享库。
src/main/jni/hello.cpp# 提供一个源文件的相对路径
src/main/jni/helloJni.cpp# 提供同一个SO文件中的另一个源文件的相对路径
)
#搜索指定的预构建库,并将该路径存储为一个变量。因为cbuild默认包含了搜索路径中的系统库,所以您只需要指定您想要添加的公共NDK库的名称。cbuild在完成构建之前验证这个库是否存在。
find_library(log-lib# 设置path变量的名称。
log #指定NDK库的名称 你想让CMake来定位。
)
#指定库的库应该链接到你的目标库。您可以链接多个库,比如在这个构建脚本中定义的库、预构建的第三方库或系统库。
target_link_libraries( hello-lib #指定目标库中。与 add_library的库名称一定要相同
${log-lib}# 将目标库链接到日志库包含在NDK。
)
#如果需要生产多个SO文件的话,写法如下
add_library( natave-lib#设置库的名称。另一个so文件的名称
SHARED# 将库设置为共享库。
src/main/jni/nataveJni.cpp# 提供一个源文件的相对路径
)
target_link_libraries( natave-lib #指定目标库中。与 add_library的库名称一定要相同
${log-lib}# 将目标库链接到日志库包含在NDK。
)

Cpp文件

下面的代码是默认生成的:


JNIEXPORT jstring JNICALL
Java_com_glee_myapplication_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}

JNIEXPORT & JNICALL


JNIEXPORT和JNICALL这两个宏(被定义在jni.h)确保这个函数在本地库外可见,并且编译器会进行正确的调用转换。


函数规范


在JNI中C/C++的函数名是有规范要求的,由以下几部分串接而成


Java_ 前缀
完全限定的类名,并用下划线 _ 作为分隔符
第一参数 JNIEnv* env
第二个参数 jobject 或 jclass
其他参数按类型映射
返回参数按类型映射
操作

这里的操作都是新的项目中操作,如果是旧项目,在相对应的创建相对应的文件。


编写 Native 方法

下面来写几个 Native 方法,由于我们是使用kotlin代码,所以将 native 关键字替换为 external 。


external 将一个声明标记为不是在Kotlin中实现(通过 JNI 访问或者在 JavaScript 中实现)


external fun oneJniStr(): String
external fun helloJniStr(): String

编写Cpp函数

在Java文件中, CMake 可以一键生成 Cpp 函数:



如果是kotlin文件,那么在 native-lib.cpp 文件里面添加下面代码:


extern "C"
JNIEXPORT jstring JNICALL
Java_top_jowanxu_jnitest_MainActivity_oneJniStr(JNIEnv *env, jobject instance) {
return env->NewStringUTF("oneJniStr1");
}
extern "C"
JNIEXPORT jstring JNICALL
Java_top_jowanxu_jnitest_MainActivity_helloJniStr(JNIEnv *env, jobject instance) {
return env->NewStringUTF("helloJniStr1");
}

因为 extern "C" 的作用是告诉编译器以 C 方式编译。


调用

然后在Activit中调用对应方法:


sample_text.text = stringFromJNI()
fab.setOnClickListener {
sample_text.text = ("${oneJniStr()}------${helloJniStr()}")
}

结果:




最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台