# NAPI组件
- [简介](#section11660541593)
- [目录](#section161941989596)
- [使用场景](#section11759141594811)
- [接口说明](#section1611515555510)
- [开发步骤](#section937267212)
- [相关仓](#section3970193518214)
## 简介
NAPI(Native API)组件是一套对外接口基于Node.js N-API规范开发的原生模块扩展开发框架。
**图 1** NAPI组件架构图

- **NativeEngine**
JS引擎抽象层,统一JS引擎在NAPI层的接口行为。
- **ModuleManager**
管理模块,用于模块加载、模块信息缓存。
- **ScopeManager**
管理NativeValue的生命周期。
- **ReferenceManager**
管理NativeReference的生命周期。
## 目录
NAPI组件源代码在/foundation/arkui/napi下,目录结构如下图所示:
```
foundation/arkui/napi
├── interfaces
│ └── kits
│ └── napi # NAPI头文件目录
├── module_manager # 模块管理
├── native_engine # NativeEngine抽象层
│ └── impl
│ └── ark # 基于Ark的NativeEngine实现
├── scope_manager # 作用域管理
└── test # 测试目录
```
## 使用场景
NAPI适合封装IO、CPU密集型、OS底层等能力并对外暴露JS接口,通过NAPI可以实现JS与C/C++代码互相访问。我们可以通过NAPI接口构建例如网络通信、串口访问、多媒体解码、传感器数据收集等模块。
## 接口说明
接口实现详见:**foundation/arkui/napi**。
**表 1** NAPI接口说明
接口分类
|
描述
|
模块注册
|
向模块管理注册模块信息的接口。
|
异常&错误处理
|
向JS抛出异常。
|
对象生命周期管理
|
作用域管理,用于限定某个作用域范围内的NAPI对象的生命周期。
|
创建JS对象
|
创建标准的对象类型。
|
C类型转NAPI类型
|
C到NAPI的类型转换。
|
NAPI类型转C类型
|
NAPI到C的类型转换。
|
获取全局实例的函数
|
获取全局实例。
|
JS值的操作
|
===、typeof、instanceof等操作符的NAPI接口。
|
JS对象的属性操作
|
操作对象属性函数集。
|
JS函数的操作
|
方法调用、实例创建。
|
对象封装
|
绑定JS对象的外部上下文关系。
|
简单异步
|
创建异步任务。
|
promise
|
创建promise对象的函数集。
|
脚本运行
|
运行JS代码。
|
## 开发步骤
下面以开发一个获取应用包名的JS接口为例介绍如何使用NAPI。
我们要实现的JS接口原型是:
```
function getAppName(): string;
```
以下是实现源码:
```
// app.cpp
#include
#include
#include "napi/native_api.h"
#include "napi/native_node_api.h"
struct AsyncCallbackInfo {
napi_env env;
napi_async_work asyncWork;
napi_deferred deferred;
};
// getAppName对应的C/C++实现函数
napi_value JSGetAppName(napi_env env, napi_callback_info info) {
napi_deferred deferred;
napi_value promise;
// 创建promise
NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
AsyncCallbackInfo* asyncCallbackInfo = new AsyncCallbackInfo {
.env = env,
.asyncWork = nullptr,
.deferred = deferred,
};
napi_value resourceName;
napi_create_string_latin1(env, "GetAppName", NAPI_AUTO_LENGTH, &resourceName);
// 创建异步任务队列
napi_create_async_work(
env, nullptr, resourceName,
// 异步任务的回调
[](napi_env env, void* data) {},
// 异步任务结束后的回调
[](napi_env env, napi_status status, void* data) {
AsyncCallbackInfo* asyncCallbackInfo = (AsyncCallbackInfo*)data;
napi_value appName;
const char* str = "com.example.helloworld";
napi_create_string_utf8(env, str, strlen(str), &appName);
// 触发回调
napi_resolve_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, appName);
napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
delete asyncCallbackInfo;
},
(void*)asyncCallbackInfo, &asyncCallbackInfo->asyncWork);
napi_queue_async_work(env, asyncCallbackInfo->asyncWork);
return promise;
}
// 模块导出入口函数
static napi_value AppExport(napi_env env, napi_value exports)
{
static napi_property_descriptor desc[] = {
DECLARE_NAPI_FUNCTION("getAppName", JSGetAppName),
};
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
return exports;
}
// app模块描述
static napi_module appModule = {
.nm_version = 1,
.nm_flags = 0,
.nm_filename = nullptr,
.nm_register_func = AppExport,
.nm_modname = "app",
.nm_priv = ((void*)0),
.reserved = {0}
};
// 注册模块
extern "C" __attribute__((constructor)) void AppRegister()
{
napi_module_register(&appModule);
}
```
对应编译脚本的实现:
```
// BUILD.gn
import("//build/ohos.gni")
ohos_shared_library("app") {
# 指定编译源文件
sources = [
"app.cpp",
]
# 指定编译依赖
deps = [ "//foundation/arkui/napi:ace_napi" ]
# 指定库生成的路径
relative_install_dir = "module"
subsystem_name = "arkui"
part_name = "napi"
}
```
应用中的JS测试代码:
```
import app from '@ohos.app'
export default {
testGetAppName() {
app.getAppName().then(function (data) {
console.info('app name: ' + data);
});
}
}
```
## 相关仓
[ArkUI框架子系统](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/ArkUI%E6%A1%86%E6%9E%B6%E5%AD%90%E7%B3%BB%E7%BB%9F.md)
[arkui\_ace\_engine](https://gitee.com/openharmony/arkui_ace_engine)
[arkui\_ace\_engine\_lite](https://gitee.com/openharmony/arkui_ace_engine_lite)
**arkui\_napi**