ArkTs之NAPI学习
1.Node-api组成架构
为了应对日常开发经的网络通信、串口访问、多媒体解码、传感器数据收集等模块,这些模块大多数是使用c++接口实现的,arkts侧如果想使用这些能力,就需要使用node-api这样一套接口去桥接c++代码。Node-api整体的架构图如下:

Node-api接口是基于node.js的一个扩展,所以在平常开发过程也可以参照node.js官网,像接口实现的功能,入参都是类似的。
Framework模块介绍
1)ModuleManager是管理对象的模块,当arkts侧调用c++时,会加载Native侧的模块到ModuleMangger,并转化为arkts对象返回上层。
2)ScopeManager:用于管理napi_value生命周期,napi_value是Node-api独特的数据类型,类似于ArkTs中的number、String等各种参数类型的统一表示形式,在Native侧代码开发中不需要感知不同类型的数据类型,统一都是napi_value。
3)ReferenceManager:用于管理引用,开发时经常会有一些跨线程的场景,这个时候就需要创建引用(napi_ref),否则就就会被GC回收掉。napi_ref用于指向napi_value,允许用户管理napi_value值的生命周期。
3)Native Engine的作用是统一ArkTS引擎在Node-API层的接口行为。
4)方舟运行时,也就是ArkTS引擎,整个Node-API模块都是跑在方舟运行时的。
2.Napi和native的交互流程
主要分为两步:模块初始化和函数调用

模块初始化
ArkTS在import一个so库的时候,会先找到ArkTS引擎,ArkTS引擎会加载模块信息到ModuleMananger,其实就是对应的dlopen函数(首次调用时加载,多次调用回去缓存查找)。之后ModuleManager会把模块信息返回给ArkTS引擎。ArkTS引擎拿到模块信息后,在native层触发模块注册,来初始化模块。注册完成之后通过底层框架返回给上层一个ArkTS对象,这个对象上挂在着c/c++侧的方法。我们拿到arkts对象后,就可以去调用c/c++的方法了。
函数调用
当arkts侧通过上述import返回的对象的调用方法时,ArkTS引擎会找到并调用对应的C/C++方法
3.Node-API支持的数据类型
napi_status:枚举数据类型,表示Node-API接口返回的状态信息。每当调用一个Node-API函数,都会返回该值,表示操作成功与否的相关信息。枚举信息如下:
typedef enum{napi_ok,napi_invalid_arg,napi_object_expected,napi_string_expected,napi_name_expected,...napi_would_deadlock
} napi_status;if (napi_ok != napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)) {return nullptr;
}
Node-API将基本数据类型公开为各种API使用的抽象。这些API应该被视为不透明的,只能通过其他Node-API调用进行自省。
- napi_value:在Native侧代码开发中不需要感知不同类型的数据,统一都是napi_value
举例说明:napi_value napiResult; napi_create_double(env, 2.0, &napiResult); - napi_env:Native侧函数入参,表示Napi-API执行时的上下文。退出native侧的时,napi_env将失效
- napi_callback_info: Native侧函数的入参,保存了ArkTS侧的参数信息,用于传递给napi_get_cb_info()函数获取ArkTS侧入参信息。
举例说明:static napi_value MyHypot(napi_env env, napi_callback_info info) {size_t argc = 2;napi_value args[2] = {nullptr};// 从info中获取参数信息到参数数组args[]napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); }4.Node-API接口
Node-API接口在Node.js提供的原生模块基础上,目前只支持部分接口。常用的部分接口介绍如下:
- napi_get_cb_info: 从给定的napi_callback_info中获取有关调用的详细信息,如参数和this指针
static napi_value MyHypot(napi_env env, napi_callback_info info) {size_t argc = 2;napi_value args[2] = {nullptr};// 从info中获取参数信息到参数数组args[]napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); } -
napi_get_value_double: 获取给定ArkTS的number类型
double valueX = 0.0;
//获取args[0]存储的参数信息并赋值给valueX,args[]中存储接受ArkTs侧参数
napi_get_value_double(env, args[0], &valueX); -
napi_create_string_utf8: 通过utf8编码的c字符串数据创建ArtTS侧String类型的数据
std::string str = "temp"; napi_value sum; //用于存储转换类型后的string类型数据 napi_create_string_utf8(env, str.c_str(), str.length(). &sum);5.案例讲解说明交互流程

目录说明
CPP目录

types/index.d.ts:定义了c++侧需要暴漏在ArkTS侧的接口
oh-package.json5是描述index.d.ts文件的
napi_init.cpp文件在里面做Native模块的注册、类型的转换以及大部分业务逻辑
ets目录

page/index.ets 里面有ArkTS调用C++
src目录
build-profile.json5:主要是配置构建信息(主要是cmakelist的构建路径,构建的时候能够找到cmakelist文件)

oh-package.json5:主要配置了一些模块本身的信息和依赖的工程

6.官方代码案例
基于Node-API开发业务功能
static napi_value MyHypot(napi_env env, napi_callback_info info)
{if ((nullptr == env) || (nullptr == info)) {OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "MyHypot", "env or exports is null");return nullptr;}// Number of parameters.size_t argc = 2;// Declare parameter array.napi_value args[2] = { nullptr };// Gets the arguments passed in and puts them in the argument array.if (napi_ok != napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)) {OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "MyHypot", "api_get_cb_info failed");return nullptr;}// Converts arguments passed in to type double.double valueX = 0.0;double valueY = 0.0;if (napi_ok != napi_get_value_double(env, args[0], &valueX) ||napi_ok != napi_get_value_double(env, args[1], &valueY)) {OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "MyHypot", "napi_get_value_double failed");return nullptr;}// The hypot method of the C standard library is called to perform the calculation.double result = hypot(valueX, valueY);napi_value napiResult;if (napi_ok != napi_create_double(env, result, &napiResult)) {OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "MyHypot", "napi_create_double failed");return nullptr;}return napiResult;
}
接口映射
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports)
{if ((nullptr == env) || (nullptr == exports)) {OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Init", "env or exports is null");return exports;}napi_property_descriptor desc[] = {{ "myHypot", nullptr, MyHypot, nullptr, nullptr, nullptr, napi_default, nullptr }};if (napi_ok != napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)) {OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Init", "napi_define_properties failed");return nullptr;}return exports;
}
EXTERN_C_END
模块注册
static napi_module demoModule = {.nm_version = 1,.nm_flags = 0,.nm_filename = nullptr,.nm_register_func = Init,.nm_modname = "hello",.nm_priv = ((void *)0),.reserved = { 0 }
};
extern "C" __attribute__((constructor)) void RegisterModule(void)
{napi_module_register(&demoModule);
}
模块构建配置
cmakelist.txt文件:
# the minimum version of CMake.
cmake_minimum_required(VERSION 3.4.1)
project(NativeTemplateDemo)
set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${NATIVERENDER_ROOT_PATH}${NATIVERENDER_ROOT_PATH}/include
)
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(hello SHARED hello.cpp)
target_link_libraries(hello PUBLIC ${hilog-lib} libace_napi.z.so libc++.a)
根目录下的build-profile.json5
{"apiType": 'stageMode',"buildOption": {"externalNativeOptions": {"path": "./src/main/cpp/CMakeLists.txt","arguments": "","abiFilters": ["arm64-v8a","x86_64"],"cppFlags": "",}},"targets": [{"name": "default","runtimeOS": "HarmonyOS"}]
}
导出native接口
/entry/oh-package.json5
{"license": "","devDependencies": {"libhello.so": "file:./src/main/cpp/types/libhello"},"author": "","name": "entry","description": "Please describe the basic information.","main": "","version": "1.0.0","dependencies": {}
}
7.更多接口说明参照官网
华为开发者学堂
相关文章:
ArkTs之NAPI学习
1.Node-api组成架构 为了应对日常开发经的网络通信、串口访问、多媒体解码、传感器数据收集等模块,这些模块大多数是使用c接口实现的,arkts侧如果想使用这些能力,就需要使用node-api这样一套接口去桥接c代码。Node-api整体的架构图如下&…...
【数据库初阶】MySQL中表的约束(上)
🎉博主首页: 有趣的中国人 🎉专栏首页: 数据库初阶 🎉其它专栏: C初阶 | C进阶 | 初阶数据结构 亲爱的小伙伴们,大家好!在这篇文章中,我们将深入浅出地为大家讲解 MySQL…...
173. 矩阵距离 acwing -多路BFS
原题链接:173. 矩阵距离 - AcWing题库 给定一个 N行 M 列的 01矩阵 A,A[i][j] 与 A[k][l]]之间的曼哈顿距离定义为: dist(i,j,k,l)|i−k||j−l|| 输出一个 N 行 M 列的整数矩阵 B,其中: B[i][j]min1≤x≤N,1≤y≤M,A…...
Linux下部署Redis集群 - 一主二从三哨兵模式
三台服务器redis一主二从三哨兵模式搭建 最近使用到了redis集群部署,使用一主二从三哨兵集群部署redis,将自己部署的过程中的使用心得分享给大家,希望大家以后部署的过程减少一些坑。 服务器准备 3台服务器 ,确定主redis和从red…...
实战设计模式之建造者模式
概述 在实际项目中,我们有时会遇到需要创建复杂对象的情况。这些对象可能包含多个组件或属性,而且每个组件都有自己的配置选项。如果直接使用构造函数或前面介绍的工厂方法来创建这样的对象,可能会导致以下两个严重问题。 1、参数过多。当一个…...
活动预告 | Microsoft Azure 在线技术公开课:使用 Azure OpenAI 服务构建生成式应用
课程介绍 通过 Microsoft Learn 免费参加 Microsoft Azure 在线技术公开课,掌握创造新机遇所需的技能,加快对 Microsoft Cloud 技术的了解。参加我们举办的“使用 Azure OpenAI 服务构建生成式应用”活动,了解如何使用包括 GPT 在内的强大的…...
ubuntu安装firefox
firefox下载地址:https://ftp.mozilla.org/pub/firefox/releases/ 卸载 sudo apt-get update dpkg --get-selections |grep firefox apt-get purge firefox 解压 tar -xjf firefox*.tar.bz2复制文件 sudo mv firefox/ /opt/firefox30sudo mv /usr/bin/firefox /…...
计算机网络原理(谢希仁第八版)第4章课后习题答案
第四章 网络层 详细计算机网络(谢希仁-第八版)第四章习题全解_计算机网络第八版谢希仁课后答案-CSDN博客 1.网络层向上提供的服务有哪两种?是比较其优缺点。网络层向运输层提供 “面向连接”虚电路(Virtual Circuit)服…...
RabbitMQ-基本使用
RabbitMQ: One broker to queue them all | RabbitMQ 官方 安装到Docker中 docker run \-e RABBITMQ_DEFAULT_USERrabbit \-e RABBITMQ_DEFAULT_PASSrabbit \-v mq-plugins:/plugins \--name mq \--hostname mq \-p 15672:15672 \-p 5672:5672 \--network mynet\-d \rabbitmq:3…...
从零开始学架构——互联网架构的演进
1 技术演进 1.1 技术演进的动力 对于新技术,我们应该站在行业的角度上思考,哪些技术我们要采取,哪些技术我们不能用,投入成本过大会不会导致满盘皆输?市场、技术、管理三者组成的业务发展铁三角,任何一个…...
python +tkinter绘制彩虹和云朵
python tkinter绘制彩虹和云朵 彩虹,简称虹,是气象中的一种光学现象,当太阳光照射到半空中的水滴,光线被折射及反射,在天空上形成拱形的七彩光谱,由外圈至内圈呈红、橙、黄、绿、蓝、靛、紫七种颜色。事实…...
重新整理机器学习和神经网络框架
本篇重新梳理了人工智能(AI)、机器学习(ML)、神经网络(NN)和深度学习(DL)之间存在一定的包含关系,以下是它们的关系及各自内容,以及人工智能领域中深度学习分支对比整理。…...
TypyScript从入门到精通
TypyScript从入门到精通 TypyScript 是什么?增加了什么环境搭建二、为何需要 TypeScript三、编译 TypeScript四、类型声明五、类型推断基本类型六、类型总览JavaScript 中的数据类型TypeScript 中的数据类型1. 上述所有 JavaScript 类型2. 六个新类型:3.…...
【MATLAB】绘制投资组合的有效前沿
文章目录 一、数据准备二、有效前沿三、代码3.1 数据批量读取、预处理3.2 绘制可行集3.3 绘制有效前沿3.4 其它-最大夏普率 一、数据准备 准备多个股票的的历史数据,目的就是找到最优的投资组合。 下载几个标普500里面的公式的股票数据吧,下载方法也可…...
matlab时频分析库
time frequency gallery...
GBase 8s 数据库备份还原
每一天都是一个新的篇章,等待着你去书写属于自己的故事!!! 一:备份 1.1.下载脚本文件,并上传到数据库服务器上相应目录。 解压后目录为: 说明: dbcomm.sh:导出注释脚本…...
C++模板相关概念汇总
文章目录 一、模板的概念与作用二、函数模板模板的非类型参数调用顺序 三、类模板四、模板的编译模型 一、模板的概念与作用 C模板是一种强大的代码复用机制,它允许程序员编写通用的代码,能够处理不同类型的数据,而无需为每种类型都重复编写…...
MYSQL------sql基础
SQL基础与简介 定义:SQL即结构化查询语言(Structured Query Language),是一种特殊目的的编程语言,用于存取数据以及查询、更新和管理关系数据库系统。作用:可以用于数据库的创建、数据的插入、查询、更新和…...
React Router 用法概览
React Router 用法 React 使得开发者能够轻松地创建交互式的单页应用(SPA),单页应用的一个常见挑战是如何处理页面导航和路由吗,React Router 就是解决这个问题的工具 路由(Router)是 React Router 的核心…...
网络安全之高防IP的实时监控精准防护
高防IP是一种网络安全设备,用于保护网络服务不受到各类攻击的影响,确保业务的持续稳定运行。它通过监控、识别和封锁恶意攻击流量,提供高级别的防护,降低业务被攻击的风险,并提升网络的稳定性和可靠性。 一、实时监控的…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...
【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?
FTP(File Transfer Protocol)本身是一个基于 TCP 的协议,理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况,主要原因包括: ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...
es6+和css3新增的特性有哪些
一:ECMAScript 新特性(ES6) ES6 (2015) - 革命性更新 1,记住的方法,从一个方法里面用到了哪些技术 1,let /const块级作用域声明2,**默认参数**:函数参数可以设置默认值。3&#x…...
图解JavaScript原型:原型链及其分析 | JavaScript图解
忽略该图的细节(如内存地址值没有用二进制) 以下是对该图进一步的理解和总结 1. JS 对象概念的辨析 对象是什么:保存在堆中一块区域,同时在栈中有一块区域保存其在堆中的地址(也就是我们通常说的该变量指向谁&…...
Mysql故障排插与环境优化
前置知识点 最上层是一些客户端和连接服务,包含本 sock 通信和大多数jiyukehuduan/服务端工具实现的TCP/IP通信。主要完成一些简介处理、授权认证、及相关的安全方案等。在该层上引入了线程池的概念,为通过安全认证接入的客户端提供线程。同样在该层上可…...
32位寻址与64位寻址
32位寻址与64位寻址 32位寻址是什么? 32位寻址是指计算机的CPU、内存或总线系统使用32位二进制数来标识和访问内存中的存储单元(地址),其核心含义与能力如下: 1. 核心定义 地址位宽:CPU或内存控制器用32位…...
