赞
踩
经常需要实现一些 C,C++ 接口的功能模块,提供给 java 层调用。
那么就需要利用 JNI 写接口提供 java 的 native 调用。
必不可少的一步就是编译 JNI 代码。
文件/目录 | 说明 |
---|---|
src/main/cpp/ | 用于存放JNI源码(C、C++等),也有人喜欢更名为 jni/ |
src/main/java/ | JNI 接口的 java 调用 |
build.gradle | 配置 CMake 编译等参数 |
CMakeLists.txt | 用于设置 JNI 代码的编译方式 |
android {
...
defaultConfig {
...
ndk {
abiFilters "armeabi-v7a"
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
ndk.abiFilters 是配置编译的CPU架构,会根据架构编译出不同架构的 .so
文件。
cmake 是配置 CMake 的编译规则文件的路径,如果和 build.gradle
同级就不需要增加目录,否则按与 build.gradle
文件的路径自行配置。
个人习惯问题,喜欢按功能模块把 JNI 源码分类:
cpp/{功能}/include/
:存放头文件
cpp/{功能}/src/
:存放源代码
cpp/
:存放 JNI 接口代码
这是个人习惯问题,大家可以无视。
一些 arm
架构的 so 库,建议放在 src/main/jniLibs/{ANDROID_ABI}/
下,因为对于动态 .so 库,程序运行时需要依赖。
在 JNI 中,需要自行根据添加 java native 的接口位置,添加 JNI 接口。
比如我想在:src/main/java/org/xxx/yyy/zzz/faceapi/FaceApiNative.java
中添加一个名为 JniJudgeHdr
的 native 接口。
public native boolean JniJudgeHdr(byte[] bytes, int width, int height, int channels);
static {
System.loadLibrary("facehdr");
}
那么我们需要增加的 JNI 接口为:
JNIEXPORT jboolean JNICALL
Java_org_xxx_yyy_zzz_faceapi_FaceApiNative_JniJudgeHdr(
JNIEnv* env, jobject /* this */
, jbyteArray jbArr_image
, jint rows
, jint cols
, jint channels
) {
...
}
基本的文件框架为:
#include <jni.h> #include <android/log.h> // #include "facehdr_jni.h" // 非必要 #include "judge_hdr/include/JudgeHdr.h" // 其它依赖的头文件 #ifdef __cplusplus extern "C" { #endif JNIEXPORT jboolean JNICALL Java_org_xxx_yyy_zzz_faceapi_FaceApiNative_JniJudgeHdr( JNIEnv* env, jobject /* this */ , jbyteArray jbArr_image , jint rows , jint cols , jint channels ) { ... } #ifdef __cplusplus } #endif
同时如果 java 需要调用 JNI 接口,就需要设置加载对应的 JNI 库。(示例 System.loadLibrary
部分)
先上内容
cmake_minimum_required(VERSION 3.4.1) # 编译后的 so 保存的位置 #set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}) # 头文件路径 include_directories( ${CMAKE_SOURCE_DIR}/src/main/cpp ${CMAKE_SOURCE_DIR}/src/main/cpp/judge_hdr/include ) file(GLOB FACE_HDR_SRC ${CMAKE_SOURCE_DIR}/src/main/cpp/facehdr_jni.cpp ) add_library( facehdr SHARED ${FACE_HDR_SRC} ) # 添加依赖库 add_library(judgehdr SHARED IMPORTED ) set_target_properties(judgehdr PROPERTIES IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/src/main/${ANDROID_ABI}/libjudgehdr.so") target_link_libraries(facehdr judgehdr) find_library( log-lib log ) target_link_libraries( facehdr ${log-lib} )
字段 | 说明 | 参数 |
---|---|---|
${CMAKE_SOURCE_DIR} | 当前 CMake 规则文件的目录位置(即 CMakeLists.txt ),所以其它文件的路径可以根据这个位置来设置 | |
include_directories | 使用到的头文件路径,可以包含多个路径的头文件 | |
file | 可以将多个源码文件打包(这个包命名为FACE_HDR_SRC ) | |
add_library | 将源码编译为对应的库(将 ${FACE_HDR_SRC} 的源码编译为 libfacehdr.so 库文件) | SHARED .so 动态库STATIC .a 静态库IMPORTED 引入外部库而不是编译生成库 |
set_target_properties | 关联需要使用的其它依赖库 | |
target_link_libraries | 把其它库一起打包到到目标库中 | |
find_library | 关联其它库(主要是 Android Studio 提供的诸如 Log 的库) |
接下来就可以运行了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。