当前位置: 首页 > news >正文

HarmonyOS实战开发:NAPI接口规范开发

简介

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 <stdio.h>
#include <string.h>
#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;// 创建promiseNAPI_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);});}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 华为 HCIP-Datacom H12-821 题库 (3)
  • vscode Git代码版本回退
  • 【生日视频制作】宝马提车交车仪式感广告展示牌AE模板修改文字软件生成器教程特效素材【AE模板】
  • javacv-ffmpeg ProcessBuilder批量旋转图片
  • Elasticsearch Suggesters API详解与联想词自动补全应用
  • Oracle rac模式下undo表空间爆满的解决
  • 公钥密码选择题
  • Cesium 台湾省白膜数据渲染
  • Java语言程序设计基础篇_编程练习题**17.17(BitOutputStream)
  • IBM退出中国,LabVIEW未来走向何方?
  • PostgreSQL技术内幕6:PostgreSQL索引技术
  • uniapp / uniapp x UI 组件库推荐大全
  • TCP/IP网络编程:第18章聊天室
  • 基于FPGA的SD卡的数据读写实现(SD NAND FLASH)
  • fast-voice-assistant
  • 【comparator, comparable】小总结
  • 03Go 类型总结
  • 4个实用的微服务测试策略
  • Bytom交易说明(账户管理模式)
  • CSS居中完全指南——构建CSS居中决策树
  • Cumulo 的 ClojureScript 模块已经成型
  • RxJS 实现摩斯密码(Morse) 【内附脑图】
  • Spring Cloud中负载均衡器概览
  • Vim 折腾记
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 基于MaxCompute打造轻盈的人人车移动端数据平台
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 想晋级高级工程师只知道表面是不够的!Git内部原理介绍
  • 在weex里面使用chart图表
  • 机器人开始自主学习,是人类福祉,还是定时炸弹? ...
  • ‌U盘闪一下就没了?‌如何有效恢复数据
  • #define与typedef区别
  • #Z0458. 树的中心2
  • $forceUpdate()函数
  • (7)STL算法之交换赋值
  • (delphi11最新学习资料) Object Pascal 学习笔记---第13章第6节 (嵌套的Finally代码块)
  • (delphi11最新学习资料) Object Pascal 学习笔记---第14章泛型第2节(泛型类的类构造函数)
  • (Oracle)SQL优化基础(三):看懂执行计划顺序
  • (附源码)spring boot智能服药提醒app 毕业设计 102151
  • (附源码)springboot太原学院贫困生申请管理系统 毕业设计 101517
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理 第13章 项目资源管理(七)
  • (十八)用JAVA编写MP3解码器——迷你播放器
  • (一) storm的集群安装与配置
  • (原创)可支持最大高度的NestedScrollView
  • (转)机器学习的数学基础(1)--Dirichlet分布
  • (转)使用VMware vSphere标准交换机设置网络连接
  • .L0CK3D来袭:如何保护您的数据免受致命攻击
  • .NET/C# 反射的的性能数据,以及高性能开发建议(反射获取 Attribute 和反射调用方法)
  • .NET_WebForm_layui控件使用及与webform联合使用
  • .net开发时的诡异问题,button的onclick事件无效
  • .NET开源快速、强大、免费的电子表格组件
  • /usr/bin/env: node: No such file or directory
  • []我的函数库
  • [12] 使用 CUDA 加速排序算法
  • [20171101]rman to destination.txt