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

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是一种网络安全设备,用于保护网络服务不受到各类攻击的影响,确保业务的持续稳定运行。它通过监控、识别和封锁恶意攻击流量,提供高级别的防护,降低业务被攻击的风险,并提升网络的稳定性和可靠性。 一、实时监控的…...

基于服务器使用 apt 安装、配置 Nginx

🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

C++ 设计模式 《小明的奶茶加料风波》

👨‍🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

Oracle11g安装包

Oracle 11g安装包 适用于windows系统,64位 下载路径 oracle 11g 安装包...

沙箱虚拟化技术虚拟机容器之间的关系详解

问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西,但是如果把三者放在一起,它们之间到底什么关系?又有什么联系呢?我不是很明白!!! 就比如说: 沙箱&#…...

【Linux】Linux安装并配置RabbitMQ

目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...

6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙

Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...

多元隐函数 偏导公式

我们来推导隐函数 z z ( x , y ) z z(x, y) zz(x,y) 的偏导公式,给定一个隐函数关系: F ( x , y , z ( x , y ) ) 0 F(x, y, z(x, y)) 0 F(x,y,z(x,y))0 🧠 目标: 求 ∂ z ∂ x \frac{\partial z}{\partial x} ∂x∂z​、 …...

文件上传漏洞防御全攻略

要全面防范文件上传漏洞,需构建多层防御体系,结合技术验证、存储隔离与权限控制: 🔒 一、基础防护层 前端校验(仅辅助) 通过JavaScript限制文件后缀名(白名单)和大小,提…...