背景
Native API(NDK)入门
Native API 是 OpenHarmony SDK 上提供的一组 native 开发接口与工具集合(也称为 NDK),方便开发者使用 C 或者 C++ 语言实现应用的关键功能。Native API 只覆盖了 OHOS 基础的一些底层能力,如 libc,图形库,窗口系统,多媒体,压缩库等,并没有完全提供类似于 JS API 上的完整的 OHOS 平台能力。在应用中使用 Native API 会编译成动态库打包到应用中。
名词概念
名词 | 名词解释 |
---|---|
Native API | OHOS SDK 里面 native 包提供的,面向三方应用开发的 Native 接口以及相应编译脚本,编译工具链。包括 C 运行时基础库 libc,3D 图形库 opengl,面向 JS 与 C 跨语言的接口 Node-API 等,具体内容详见下表。 |
NDK | Native Develop Kit 的缩写,在 OHOS 上就是 Native API;Native API 是官方名字,NDK 指代相同意思。 |
SDK CAPI | OHOS Native API 中的 C 语言接口,以及工具链部分,当前 OHOS 的 Native API 里面只包含 C 语言接口,因此 Native API 与 CAPI 意思一样,建议交流的时候使用 CAPI,防止 Native API 与 napi 缩写混用。 |
Node-API | 曾用名 napi,是 OHOS 中提供 JS 与 C 跨语言调用的接口,是 Native API 接口中的一部分. 该接口在 Node.js 提供的 Node-API 基础上扩展而来,但不完全与 Node.js 中的 Node-API 完全兼容。 |
napi | Node-API 的曾用名,当前 Node-API 头文件中的接口仍然以 napi_开头,不建议使用。 |
Native API 构成介绍
Native API 目录结构
Native API 在 SDK 包的位置为$(SDK_ROOT)/native 目录,主要有以下几个部分组成
目录 | 功能说明 |
---|---|
build | 应用中编译动态库的 toolchain cmake 脚本;这个目录下 ohos.toolchain.cmake 文件定义了给 OHOS 交叉编译选项 |
build-tools | 放置编译构建的工具,如 cmake |
docs | Native API 接口参考文档,通过 doxgen 从头文件中提取出来 |
llvm | 支持 OHOS ABI 的 llvm 交叉编译器 |
sysroot | 放置编译链接的依赖文件目录,包含头文件,动态库等 |
Native API 接口(4.0 Release)
接口分类 | 接口功能 | 引入版本 |
---|---|---|
标准 C 库 | 以 musl 为基础提供的标准 c 库接口,当前提供了 1500+ 的接口 | 8 |
标准 C++ 库 | c++ 运行时库 libc++_shared,此库在打包的时候需要打包或者静态链接到应用中 | 8 |
日志 | 打印日志到系统的 hilog 接口 | 8 |
Node-API | ArkUI 提供的,方便应用开发接入 JS 应用环境的一组类 Node-API(也叫 napi),是属于 Native API 的一部分 | 8 |
XComponent | ArkUI XComponent 组件中的 surface 与触屏事件接口,方便开发者开发高性能图形应用 | 8 |
libuv | ArkUI 集成的三方的异步 IO 库 | 8 |
libz | zlib 库,提供基本的压缩,解压接口 | 8 |
Drawing | 系统提供的 2D 图形库,可以在 surface 进行绘制 | 8 |
OpenGL | 系统提供的 openglv3 接口 | 8 |
Rawfile | 应用资源访问接口,可以读取应用中打包的各种资源 | 8 |
OpenSLES | 用于 2D,3D 音频加速的接口库 | 8 |
Mindspore | AI 模型接口库 | 9 |
包管理 | 包服务接口,方便查询应用包信息 | 8 |
Native API 相关资料
- Native API 参考,介绍各个 API 参考手册
- Native API 中支持的标准库,介绍 Native API 支持的开源标准库
- Native API 开发指南,结合具体的例子,场景介绍各类接口的使用
- 如何在 Cmake 工程中使用 NDK,介绍如何使用使用 NDK 开发一个 CMake 工程
- Node-API 在应用工程中的使用指导, 如何使用 Node-API 接口
简单应用
如何开发应用?
-
DevEco IDE 创建工程选择“Native C++”模板:
**编译运行后,点击 helloworld 打印输出有:Test NAPI 2 + 3 = 5**
-
ArkUI 部分:
import hilog from '@ohos.hilog'; //导入hilog import testNapi from 'libentry.so'; //导入nativeC++模块 @Entry @Component struct Index { @State message: string = 'Hello World'; build() { Row() { Column() { Text(this.message) .fontSize(50) .fontWeight(FontWeight.Bold) .onClick(() => { //调用nativeC++代码 hilog.info(0x0000, 'testTag', 'Test NAPI 2 + 3 = %{public}d', testNapi.add(2, 3)); }) } .width('100%') } .height('100%') } }
-
nativeC++ 部分由 CMake 和 C++ 代码两部分组成:
-
CMake:
# the minimum version of CMake. cmake_minimum_required(VERSION 3.4.1) project(MyNDKApplication) # 编译路径 set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) # 编译头文件路径 include_directories(${NATIVERENDER_ROOT_PATH} ${NATIVERENDER_ROOT_PATH}/include) # 编译对象entry是对应用层可见的so,即import testNapi from 'libentry.so' add_library(entry SHARED hello.cpp) # 这是link命令,libace_napi 这个就是node-api需要用的so库; target_link_libraries(entry PUBLIC libace_napi.z.so)
-
C++:
#include "napi/native_api.h" // 对外node-api方法,对应testNapi.add(2, 3) static napi_value Add(napi_env env, napi_callback_info info) { size_t requireArgc = 2; size_t argc = 2; napi_value args[2] = {nullptr}; napi_get_cb_info(env, info, &argc, args , nullptr, nullptr); napi_valuetype valuetype0; napi_typeof(env, args[0], &valuetype0); napi_valuetype valuetype1; napi_typeof(env, args[1], &valuetype1); double value0; napi_get_value_double(env, args[0], &value0); double value1; napi_get_value_double(env, args[1], &value1); napi_value sum; napi_create_double(env, value0 + value1, &sum); return sum; } // 模块初始化方法,对应的方法在这加入对外描述队列 EXTERN_C_START static napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor desc[] = { { "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr } }; napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); return exports; } EXTERN_C_END // 模块声明,import时候调用 static napi_module demoModule = { .nm_version = 1, .nm_flags = 0, .nm_filename = nullptr, .nm_register_func = Init, .nm_modname = "entry", .nm_priv = ((void*)0), .reserved = { 0 }, }; // 模块入口注册 extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
-
如何使用系统 NDK?
上面例子运行起来后,c++ 部分是没有打印信息的,若想看到对应的打印信息,则需要调用 hilog 进行输出,修改如下:
-
cmake 修改:
# the minimum version of CMake. cmake_minimum_required(VERSION 3.4.1) project(MyNDKApplication) set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) include_directories(${NATIVERENDER_ROOT_PATH} ${NATIVERENDER_ROOT_PATH}/include) # 增加hiloglib库引用 find_library( # Sets the name of the path variable. hilog-lib # Specifies the name of the NDK library that # you want CMake to locate. hilog_ndk.z ) add_library(entry SHARED hello.cpp) # 增加hiloglib库连接 target_link_libraries(entry PUBLIC ${hilog-lib} libace_napi.z.so)
-
c++ 文件修改:
// 增加hilog头文件 #include <hilog/log.h> #include "napi/native_api.h" static napi_value Add(napi_env env, napi_callback_info info) { // 增加打印输出 const unsigned int LOG_PRINT_DOMAIN = 0xFF00; OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Init", "Init begins"); size_t requireArgc = 2; size_t argc = 2; napi_value args[2] = {nullptr}; ...
-
输出:
08-07 05:40:25.079 15167-15167 A0ff00/Init com.example.myndkapplication I Init begins 08-07 05:40:25.079 15167-15167 A00000/testTag com.example.myndkapplication I Test NAPI 2 + 3 = 5
具体原理是什么?
1、PC 端 OHOS SDK 里包括了 native 对应的库文件和头文件;
2、OHOS 源码可以编译出带 NDK 的 FullSDK,也可以从 CI 网址下载;
# Generate NDK library from NDK description file.
#
# Variables:
# ndk_description_file:
# min_compact_version: string specifies the minimal compactible version of NDK.
# set to major_version in default.
#
template("ohos_ndk_library") {
forward_variables_from(invoker, [ "testonly" ])
assert(defined(invoker.ndk_description_file),
"ndk description file is necessary ")
...
// 在GN里用ohos_ndk_library生成ndk库和头文件,如
ohos_ndk_library("libhilog_ndk") {
output_name = "hilog_ndk"
ndk_description_file = "./libhilog.ndk.json"
min_compact_version = "1"
system_capability = "SystemCapability.HiviewDFX.HiLog"
}
ohos_ndk_headers("hilog_header") {
dest_dir = "$ndk_headers_out_dir/hilog"
sources = [ "./include/hilog/log.h" ]
}
// ndk_description_file 对应的 libhilog.ndk.json 文件里声明了导出的接口函数
[
{
"name": "OH_LOG_Print"
},
{
"name": "OH_LOG_IsLoggable"
}
]
// ohos 编译fullsdk的命令: ./build.sh --product-name ohos-sdk
使用建议
建议使用 Native API 的场景
主要有如下一些
- 应用性能敏感代码,比如游戏,物理模拟等计算密集型场景
- 需要复用已有的 C 或 C++ 库
- 需要针对 CPU 特性进行专项定制的库,如 neon 加速
不建议使用 Native API 的场景
- 写一个纯 native 的的 OHOS 应用
- 希望在尽可能多的 OHOS 设备上保持兼容的应用
维测能力
总结
- NDK 方式是应用层直接调用底层库或者三方库目前看最常规的方式;
- 4.0(API10)有 ndk 46 个,3.2(API9)有 ndk 28 个,实质代码里有更多的 ndk,RK 的原因没有编出更多,比如 sensor 部分就没有编译出来;
- 划重点,NDK 里有两种 api:node-api,用于 arkts 和 c++ 调用和传递数据;c/c++ api,可以把动态库打包成应用侧 c++ 直接调用的接口;
写在最后
有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)文档用来跟着学习是非常有必要的。
这份鸿蒙(HarmonyOS NEXT)文档包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。
希望这一份鸿蒙学习文档能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!
获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习文档
鸿蒙(HarmonyOS NEXT)5.0最新学习路线
有了路线图,怎么能没有学习文档呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。
获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习文档
《鸿蒙 (OpenHarmony)开发入门教学视频》
《鸿蒙生态应用开发V3.0白皮书》
《鸿蒙 (OpenHarmony)开发基础到实战手册》
OpenHarmony北向、南向开发环境搭建
《鸿蒙开发基础》
●ArkTS语言
●安装DevEco Studio
●运用你的第一个ArkTS应用
●ArkUI声明式UI开发
.……
《鸿蒙开发进阶》
●Stage模型入门
●网络管理
●数据管理
●电话服务
●分布式应用开发
●通知与窗口管理
●多媒体技术
●安全技能
●任务管理
●WebGL
●国际化开发
●应用测试
●DFX面向未来设计
●鸿蒙系统移植和裁剪定制
……
《鸿蒙进阶实战》
●ArkTS实践
●UIAbility应用
●网络案例
……