OpenHarmony开发实践-鸿蒙napi开发实践
鸿蒙napi开发实践
前言
HarmonyOS Node-API是基于Node.js 18.x LTS的Node-API规范扩展开发的机制,为开发者提供了ArkTS/JS与C/C++模块之间的交互能力。它提供了一组稳定的、跨平台的API,可以在不同的操作系统上使用。
一般情况下HarmonyOS应用开发使用ArkTS/JS语言,但部分场景由于性能、效率等要求,比如游戏、物理模拟等,需要依赖使用现有的C/C++库。Node-API规范封装了I/O、CPU密集型、OS底层等能力并对外暴露C接口,使用C/C++模块的注册机制,向ArkTS/JS对象上挂载属性和方法的方式来实现ArkTS/JS和C/C++的交互。主要场景如下:
-
系统可以将框架层丰富的模块功能通过Node-API的模块注册机制对外暴露ArkTS/JS的接口,将C/C++的能力开放给应用的ArkTS/JS层。
-
应用开发者也可以选择将一些对性能、底层系统调用有要求的核心功能用C/C++封装实现,再通过ArkTS/JS接口使用,提高应用本身的执行效率。
开发步骤
第一步:创建Native C++工程
- 在DevEco Studio中New > Create Project,选择Native C++模板,点击Next,选择API版本,设置好工程名称,点击Finish,创建得到新工程。、

-
创建工程后工程结构可以分两部分,cpp部分和ets部分
目录结构如下:

entry:应用模块,编译构建生成一个HAP。
-
src > main > cpp > types:用于存放C++的API接口描述文件
-
src > main > cpp > types > libentry > index.d.ts:描述C++ API接口行为,如接口名、入参、返回参数等。
-
src > main > cpp > types > libentry> oh-package.json5:配置.so三方包声明文件的入口及包名。
-
src > main > cpp > CMakeLists.txt:CMake配置文件,提供CMake构建脚本。
-
src > main > cpp > napi_init.cpp:定义C++ API接口的文件。
-
**src > main > ets:**用于存放ArkTS源码。
native侧的实现
设置模块注册信息
ArkTS侧import native模块时,会加载其对应的so。加载so时,首先会调用napi_module_register方法,将模块注册到系统中,并调用模块初始化函数。
napi_module有两个关键属性:一个是.nm_register_func,定义模块初始化函数;另一个是.nm_modname,定义模块的名称,也就是ArkTS侧引入的so库的名称,模块系统会根据此名称来区分不同的so。
我们对napi_init.cpp文件的代码进行解析
#include "napi/native_api.h"// 定义 N-API 函数 Add:接收两个数字参数,返回它们的和(N-API 标准静态函数声明)
// env:N-API 环境句柄(用于访问所有 N-API 函数)
// info:回调信息句柄(包含函数调用时的参数、this 指针等上下文)
static napi_value Add(napi_env env, napi_callback_info info)
{// 1. 初始化参数相关变量size_t argc = 2; // 期望接收的参数个数(此处为 2 个数字)napi_value args[2] = {nullptr}; // 存储传入参数的数组(napi_value 是 N-API 中所有值的通用类型)// 2. 获取函数调用时的实际参数// 作用:从 info 中提取参数到 args 数组,同时更新实际接收的参数个数到 argc// 参数说明:env(环境句柄)、info(回调信息)、&argc(实际参数个数输出)、args(参数存储数组)、// nullptr(不获取 this 指针)、nullptr(不获取额外数据)napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);// 3. (可选,此处仅获取类型未做校验)获取两个参数的数据类型napi_valuetype valuetype0; // 存储第一个参数的数据类型(如数字、字符串等)napi_typeof(env, args[0], &valuetype0); // 获取 args[0] 的数据类型napi_valuetype valuetype1; // 存储第二个参数的数据类型napi_typeof(env, args[1], &valuetype1); // 获取 args[1] 的数据类型// 4. 将 N-API 数值(napi_value)转换为 C 语言的 double 类型double value0; // 存储第一个参数的 double 值// 作用:将 args[0](N-API 数值)解析为 double 并写入 value0napi_get_value_double(env, args[0], &value0);double value1; // 存储第二个参数的 double 值napi_get_value_double(env, args[1], &value1); // 解析 args[1] 为 double// 5. 计算总和并转换为 N-API 数值类型napi_value sum; // 存储结果的 N-API 数值// 作用:创建一个新的 N-API 双精度数值(value0 + value1),并写入 sumnapi_create_double(env, value0 + value1, &sum);// 6. 返回计算结果(N-API 函数必须返回 napi_value 类型)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
// 准备模块加载相关信息,将上述Init函数与本模块名等信息记录下来。
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 },
};
// 加载so时,该函数会自动被调用,将上述demoModule模块注册到系统中
extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
{napi_module_register(&demoModule);
}
我们在napi_init.cpp中定义了一个add的方法,然后我们需要在Index.d.ts中暴露出去
export const add: (a: number, b: number) => number;
ArkTS中调用
import { hilog } from '@kit.PerformanceAnalysisKit';
//引入napi的so库
import testNapi1 from 'libentry.so';const DOMAIN = 0x0000;@Entry
@Component
struct Index {@State message: string = 'Hello World';build() {Row() {Column() {Text(this.message).fontSize($r('app.float.page_text_font_size')).fontWeight(FontWeight.Bold).onClick(() => {this.message = 'Welcome';//调用即可hilog.info(DOMAIN, 'testTag', 'Test NAPI 2 + 3 = %{public}d', testNapi1.add(2, 3));})}.width('100%')}.height('100%')}
}
其中在entry模块中引用so库,是在oh-package.json5中配置napi的依赖路径,配置代码如下
{"name": "entry","version": "1.0.0","description": "Please describe the basic information.","main": "","author": "","license": "","dependencies": {"libentry.so": "file:./src/main/cpp/types/libentry"}
}
手动配置时,需要把鼠标放到路径下,ohpm install 一下,安装一下依赖
至此,我们就可以分两部分,napi和ArkTS各自开发各自的功能
欢迎大家跟我一起学习鸿蒙开发知识,加入我的班级,参与HarmonyOS赋能资源丰富度建设(第四期)-夏文强,获得HarmonyOS应用开发者认证 每月对前200名学员进行激励,活动期间共计激励1000名
华为开发者学堂
