NAPI是什么?
简单点理解就是在Openharmony里,实现上层js或ets应用与底层C/C++之间交互的框架。
Openharmony里的官方解释:NAPI(Native API)组件是一套对外接口基于Node.js N-API规范开发的原生模块扩展开发框架。还有NAPI适合封装IO、CPU密集型、OS底层等能力并对外暴露JS接口,通过NAPI可以实现JS与C/C++代码互相访问。我们可以通过NAPI接口构建例如网络通信、串口访问、多媒体解码、传感器数据收集等模块。
napi概念来源于Node.js,openharmony沿用了napi的原理,根据自己的js引擎,重写了类napi接口,并保留了napi的语法。其用于在系统层创建js对象,或从js运行环境中获取js对象或方法。通过napi,系统层可以向应用层提供napi接口,暴露系统层的函数方法。
napi文档链接NAPI组件开发步骤源码文档下面是详解:
一、napi源码实现
总结:上面的图主要是在C++中使用N-API创建一个简单的Node.js原生模块
该模块包含一个名为add的方法。通过__attribute__((constructor))编译器指令,该模块在Node.js环境启动时自动注册,使得JavaScript代码可以访问这个原生模块及其功能。
详细分析:
1. 注册模块
// 注册模块
extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
{
// demoModule似乎是一个使用Node.js的N-API(Node.js原生插件API)创建的模块。
// N-API是Node.js提供的一套API,允许开发者用C/C++编写原生模块,这些模块可以在Node.js环境中被JavaScript代码调用。
napi_module_register(&demoModule);
2. 模块描述
// app模块描述
// demoModule 是一个napi_module结构体实例,它描述了要注册的模块
static napi_module demoModule = {
.nm_version = 1,
.nm_flags = 0,
.nm_filename = nullptr,
//指向模块的初始化函数即Init函数
.nm_register_func = Init,
.nm_modname = "entry",
.nm_priv = ((void*)0),
.reserved = { 0 },
};
3. 接口定义
//接口定义
//napi_env env:这是一个指向N-API环境的指针,它包含了调用Node.js原生模块时所需的所有上下文信息。
//napi_value exports:这是一个指向Node.js的exports对象的指针,用于将原生模块的函数或属性暴露给JavaScript。
static napi_value Init(napi_env env, napi_value exports)
{
//这是一个napi_property_descriptor结构体数组,用于描述要添加到exports对象的属性和方法,它定义了一个名为add的方法。
//最重要的是这里,最终干了什么,就是这些函数的处理,这里是ts的函数,但要在底层去实现他
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;
}
4. 接口实现
static napi_value Add(napi_env env, napi_callback_info info)
{
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;
}
到此,我们已经对外导出了1个napi接口,应用端可以调用这个接口。
二、调用接口
1. 接口定义
2. 工程级依赖配置文件
3. 导入库
//在调用napi前,我们需要导入napi库
import testNapi from 'libentry.so';
4. 调用接口
struct Index {
@State message: string = 'Hello World';
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
//导入完库后,我们就可以通过导入的变量直接调用对应的napi接口
hilog.info(0x0000, 'testTag', 'Test NAPI 2 + 3 = %{public}d', testNapi.add(2, 3));
})
}
.width('100%')
}
.height('100%')
}
}