Openharmony应用NAPI详解--基础篇

NAPI篇【1】——如何创建含NAPI的OpenHarmony工程 NAPI,全称 Native API,是OpenHarmony系统中的一套原生模块拓展开发框架。基于Nodejs中的N-API开发,为开发者提供了JS与C/C++不同语言模块之间的相互访问,交互的能力,方便开发者使用C或者C++语言实现应用的关键功能。在应用中使用Native API会编译成动态库打包到应用中。 阅读详情
AI摘要

NAPI是OpenHarmony中的一个组件,用于实现JS和C++之间的交互。它提供了一套基于Node.jsN-API规范的接口,支持同步和异步调用,包括回调和Promise方式。文章通过代码示例展示了如何定义和使用这些接口,以及在C++中实现接口的方法和数据类型转换过程。

NAPI是什么?

简单点理解就是在Openharmony里,实现上层js或ets应用与底层C/C++之间交互的框架。

Openharmony里的官方解释:NAPI(Native API)组件是一套对外接口基于Node.js N-API规范开发的原生模块扩展开发框架。还有NAPI适合封装IO、CPU密集型、OS底层等能力并对外暴露JS接口,通过NAPI可以实现JS与C/C++代码互相访问。我们可以通过NAPI接口构建例如网络通信、串口访问、多媒体解码、传感器数据收集等模块。

now,以Openharmon V3.1-Release版本为例,抽取代码实例,分为两部份进行分析。

面向上层js或ets接口

1.定义接口

接口描述文件在Openharmony里.d.ts后缀结束。

在分布式文件服务(//foundation/filemanagement/dfs_service)的@ohos.sendfile.d.ts文件中

import {AsyncCallback, Callback} from "./basic";

declare namespace SendFile {
  // 异步接口----回调方式
  function sendFile(deviceId: string, sourPath: Array<string>, destPath: Array<string>, fileCount: number, callback: AsyncCallback<number>);
  // 异步接口----Promise方式
  function sendFile(deviceId: string, sourPath: Array<string>, destPath: Array<string>, fileCount: number): Promise<number>;
  // 异步接口----回调方式
  function on(type: 'sendFinished' | 'receiveFinished', callback: AsyncCallback<TransResult>): void;
  // 同步接口
  function off(type: 'sendFinished' | 'receiveFinished'): void;
}

export default SendFile;

以上为应用开发者提供了四个的JS接口,分为同步接口与异步接口两类,异步接口又分为回调方式与Promise。

2.App应用开发者的JS代码简单导入一下模块就可以直接调用了。

// 同步调用
import myapp1 from "@ohos.SendFile"
var result = myapp1.off(/* 参数自填*/);

// 异步调用
/** call back 方式的异步调用 */
myapp1.sendFile("xxxx", sourPath, destPath, 4, function (err, ret) {
    ......
});
/** Promise 方式的异步调用 */
var  promiseObj = myapp1.sendFile("xxxx", sourPath, destPath, 4).then(data => {
    ......
}).catch(error => {
    ......
});

3.关于d.ts的注意事项

1.自定义d.ts接口文件时,在应用开发工具(DevEco Studio)里需要将此文件放入Openharmony sdk所在目录中,例如,在作者的本机为D:\Program\Huawei\OpenHarmony3.1\Sdk\ets\3.1.5.5\api与D:\Program\Huawei\OpenHarmony3.1\Sdk\js\3.1.5.5\api,根据应用调用者(js或ets)的不同放入不同的目录。

2.Openharmony已有d.ts接口文件,根据文件中注释里说的@since 9对应相应的导入sdk版本后,不需要另做导入dts。

面向C++的接口实现

1.模块注册与方法名映射

// foundation/filemanagement/dfs_service/frameworks/js/napi/src/sendfile_napi.cpp
napi_value SendFileExport(napi_env env, napi_value exports)
{
    const char className[] = "SendFile";
    static napi_property_descriptor desc[] = {
        DECLARE_NAPI_FUNCTION("sendFile", JsSendFile),
        DECLARE_NAPI_FUNCTION("on", JsOn),
        DECLARE_NAPI_FUNCTION("off", JsOff),
    };
    napi_value sendFileClass = nullptr;

    napi_define_class(env, className, sizeof(className), JsConstructor, nullptr,
        sizeof(desc) / sizeof(desc[0]), desc, &sendFileClass);

    napi_set_named_property(env, exports, "SendFile", sendFileClass);

    SendFile::RegisterCallback();
    return exports;
}
// 模块注册
NAPI_MODULE(sendfile, SendFileExport)
  • 通过NAPI_MODULE与DECLARE_NAPI_FUNCTION两个宏分别完成模块注册与方法名映射。

  • 这里dts定义了两个sendFile接口,为何只需要定义映射一个?

因为对js或ets来说sendFile对外接口名相同,在C++实现时根据传入的参数个数或者参数类型来判断js或ets调用哪个函数。

2.同步接口

根据映射,同步接口off对应C++的实现是JsOff。

  • 函数声明

每一个映射后的函数,必须是参数napi_env env, napi_callback_info cbinfo,返回值为napi_value。

// foundation/filemanagement/dfs_service/frameworks/js/napi/src/sendfile_napi.cpp
napi_value JsOff(napi_env env, napi_callback_info cbinfo)
{
......
}

为了实现js或ets调用,NAPI框架需要解决以下问题:数据传递与转换

js/ets传入的入参、得到的返回结果,需要转换成C/C++代码可以操作的数据类型,NAPI框架引入了一个中间的数据类型,来分别对应上层js/ets与C/C++的类型,以及数据类型的操作方法。

  • 获取入参

napi_get_cb_info从cbinfo参数中js传入参数,以下为函数说明

// napi_get_cb_info从napi_callback_info类型的参数中得到回调的参数等数据
napi_status napi_get_cb_info(
  napi_env env,
  napi_callback_info cbinfo, // 传入回调函数的回调信息
  size_t *argc,             // 作为入参传入`argv`数组的大小,并将接收实际的参数个数
  napi_value *argv,         // 存放参数的buffer
  napi_value *this_arg,     // Javascript中的`this`
  void** data               // 接收数据指针
);

argc为传入参数个数,argv为传入参数数组,此时参数的类型都为napi_value。

通过napi_typeof方法获取入参的实际类型

// napi_typeof获取指定对象的类型
napi_status napi_typeof(
  napi_env env,
  napi_value value,         // 将要获取类型的Javascript值
  napi_valuetype *result    // Javascript值的类型
);

根据d.ts的描述,off传入的只有一个参数,参数类型为字符串。

// foundation/filemanagement/dfs_service/frameworks/js/napi/src/sendfile_napi.cpp
napi_value JsOff(napi_env env, napi_callback_info cbinfo)
{
    size_t requireArgc = 1;
...
    NAPI_ASSERT(env, argc == requireArgc, "requires 1 parameter"); //参数个数为1 
    napi_valuetype eventValueType = napi_undefined;
	napi_typeof(env, argv[0], &eventValueType);
	NAPI_ASSERT(env, eventValueType == napi_string, "type mismatch for parameter 1");//参数类型为napi_string,即为NAPI中定义一种字符串
...
}
  • 类型转换为C/C++可识别的类型

napi_get_value_string_utf8方法将napi_string转换char*

napi_status napi_get_value_string_utf8(napi_env env,
  napi_value value,
  char* buf,
  size_t bufsize,
  size_t* result);
// foundation/filemanagement/dfs_service/frameworks/js/napi/src/sendfile_napi.cpp
napi_value JsOff(napi_env env, napi_callback_info cbinfo)
{
...
    char* type = nullptr;
    size_t typeLen = 0;
    napi_get_value_string_utf8(env, argv[0], nullptr, 0, &typeLen);

    NAPI_ASSERT(env, typeLen > 0, "typeLen == 0");
    type = new char[typeLen + 1];

    napi_get_value_string_utf8(env, argv[0], type, typeLen + 1, &typeLen);
...
}
  • 返回值

C++没有返回值,此时JsOff将nullptr返回。

NAPI框架没有nullptr,通过napi_get_undefined将nullptr转换成napi_undefined。

napi_value JsOff(napi_env env, napi_callback_info cbinfo)
{
...
    napi_value result = nullptr;
    napi_get_undefined(env, &result);
    return result;
}

后续更精彩

1.Openharmony应用NAPI详解--进阶篇

开源鸿蒙南向嵌入学习笔记——NAPI框架学习(一) NAPI其实是最早应该是来自node.js中的一个拓展库(也可以说是一整套API接口),叫Node-API,叫做N-API。是用来构建本地插件的API,将所有的nodejs底层数据结构黑盒化,封装成二进制接口,这样就可以实现不同版本的Node.js使用同样的接口,其目的是为了简化开发和维护。这是一条使用框架编写一些C/C++代码作为JS的接口的时需要注意的事情。黄同学在做一个板子的sample的时候发现,某个smaple的样例源码无法跑通,除了一些简单的语法错误,最主要的是函数定义时的参数类型。 阅读详情

相关推荐

鸿蒙开发 napi系列学习基础篇——NAPI数据类型转换与同步调用

示例代码中,我们使用napi_create_string_utf8函数将C/C++ string转换成NAPI类型——napi_value。NAPI定义API方法时的接收参数为(napi_env, napi_callback_info),其中napi_callback_info为上下文的信息。因传入的参数是Javascript值类型,并被框架封装成统一的唯一类型——napi_value类型,为了能够进行计算,我们需要获取其对应在C/C++中的类型的值。以下列出常用的几种接口。中的相关接口进行转换。

m0_70748458的博客 3153

利用napi编写node的C++扩展进阶之多次调用回调函数的实现方案

最近项目上要实现一个nodejs 的 C++扩展模块, 主要是用于将从海康接口处得到的视频流进行转发,因为我们的设备并不支持无插件开发, 所以得自行探索一下,故此记录一下网上少有的难点。多线程调用js回调函数

打不死的小五 7759

OpenHarmony实战—— 手撕 NAPI框架

NAPI是JavaScript与C++交互的桥梁。在OpenHarmony中,Javascript代码在运行时由ArkUI的JS引擎解释执行,C++代码则通过NAPI接口访问JS引擎中的Javascript上下文,从而实现与JS变量、方法之间的相互调用。

xianglizaibie的博客 753

OpenHarmony之NAPI框架介绍

这一切是怎么做到的呢?需要通过对应的NAPI方法实现,例如:napi_get_value_int32() --- js变量转为c++整形napi_get_value_string_utf8() --- js变量转为c++字符串napi_get_value_bool() --- js变量转为c++布尔值。在OpenHarmony中,Javascript代码在运行时由ArkUI的JS引擎解释执行,C++代码则通过NAPI接口访问JS引擎中的Javascript上下文,从而实现与JS变量、方法之间的相互调用。

OpenHarmony_dev的博客 3165

鸿蒙5.0【OpenHarmony】NAPI框架

NAPI 的概念源自 Nodejs,为了实现 javascript 脚本与 C++库之间的相互调用,Nodejs 对 V8 引擎的 api 做了一层封装,称为 NAPI。可以在 Nodejs 官网([nodejs.org/dist/latest…])上查看各种 NAPI 接口定义说明。

2401_82772199的博客 1663

openHarmony使用Napi开发样例

NAPI的开发。可以添加函数,c++文件和c++打的so

m0_49071631的博客 2910

【OpenHarmony】napi基础知识学习

Node.js N-API 是为构建原生插件提供的稳定接口,与JavaScript运行时隔离,确保兼容性。其特点包括:通过状态码返回调用结果、使用出参传递返回值、将JS值抽象为napi_value等。开发时需C/C++工具链,推荐使用node-gyp或CMake.js构建。为方便分发,可使用node-pre-gyp等工具上传预编译二进制文件。N-API提供C语言接口,另有node-addon-api封装C++版本。该API设计确保底层JS引擎更新时无需重新编译插件。

最简示例破局!基础用法秒会,深层原理不绕弯。 2032

NAPI篇【4】——NAPI应用点亮一个LED

OpenHarmony的NAPI功能为开发者提供了JS与C/C++不同语言模块之间的相互访问,交互的能力,使得开发者使用C或者C++语言实现应用的关键功能。如操作开发板中某个GPIO节点的状态(OpenHarmony并没有提供直接操作GPIO口状态的API),点亮一个LED灯。本篇基于前3篇NAPI的讲解总结,做一个控制开发板上LED灯状态的应用作为完结篇。

Devlin_的博客 1589

Node.js N-API获取方法参数

在C/C++中通过N-API提供的方法获取Native方法被Node.js调用时所传递的参数。

Ghosind 6131

OpenHarmony 实战开发之NAPI框架介绍

NAPI是JavaScript与C++交互的桥梁。在OpenHarmony中,Javascript代码在运行时由ArkUI的JS引擎解释执行,C++代码则通过NAPI接口访问JS引擎中的Javascript上下文,从而实现与JS变量、方法之间的相互调用。

m0_70748458的博客 838

NAPI篇【3】——如何编写一个NAPI函数

在NAPI篇【2】中讲解了cpp目录中各文件的作用,默认生成的hello.cpp源代码文件中,包含NAPI函数编写、定义与注册,本篇以分析hello.cpp的Add函数用来讲解一下NAPI函数的编写。首先,明确一个概念,NAPI的目的是提供了JS与C/C++不同语言模块之间的相互访问(主要是数据的传递),但是JS与C/C++是不同语言,无法直接进行数据传递,需要进行数据类型转化,这需要一座桥梁。

Devlin_的博客 1718

NAPI篇【2】——OpenHarmony含NAPI工程cpp详解

EXTERN_C_START //开始标志static napi_value Init(napi_env env, napi_value exports) //Init定义模块名//需要引出的NAPI功能函数,这以Add函数为例,"add"对应 libentry 目录下index.d.ts 文件中导出的函数名//"add"自定义函数名,用于ets调用,注意与index.d.ts 文件中导出名一致;Add注册定义的函数名。//...//定义导出的函数可以有多个。

Devlin_的博客 1926

鸿蒙开发 napi系列学习基础篇——如何通过DevEco Studio开发一个NAPI工程

NAPI(Native API)是OpenHarmony系统中的一套原生模块扩展开发框架,它基于Node.js N-API规范开发,为开发者提供了JavaScript与C/C++模块之间相互调用的交互能力。如下图所示:OpenHarmony系统系统可以将框架层丰富的模块功能通过js接口开放给上层应用使用。应用开发者也可以选择将一些对性能、底层系统调用有要求的核心功能用C/C++封装实现,再通过js接口使用,提高应用本身的执行效率。

m0_70748458的博客 2123

OpenHarmony之NAPI框架

NAPI是JavaScript与C++交互的桥梁。在OpenHarmony中,Javascript代码在运行时由ArkUI的JS引擎解释执行,C++代码则通过NAPI接口访问JS引擎中的Javascript上下文,从而实现与JS变量、方法之间的相互调用。鸿蒙应用开发与鸿蒙系统开发哪个更有前景?嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~对于大前端开发来说,转鸿蒙开发究竟是福还是祸?鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?记录一场鸿蒙开发岗位面试经历~持续更新中……

adaedwa187545的博客 1182

OpenHarmony ArkUI实战开发-NAPI数据类型

在前两篇文章里笔者简单介绍了 NAPI 工程结构以及生成的 cpp 源码部分,其中 JS 应用层传递过来的数据被封装在了 napi_value 中,使用前先要转换成对应的 C/C++ 数据类型,C/C++ 端的数据也要转换成 napi_value 数据类型传递给 JS 应用层,本节笔者简单介绍一下 NAPI 中提供的数据类型转换相关知识点。

m0_70748458的博客 1246

Linux - xarray 工具类

第三层节点直接与绿色的值绑定,若需要像数组一样通过下标访问绿色的值对象那么需要给每一个节点进行编码,这样通过根节点即可访问到具体的对象。对于未使用到的小数组不申请空间,这样只需设计一种方法将这些非连续的小数组在一个数据结构中组织在一起即可,对于这个数组结构需要具有结构紧凑并且能够快速定位到对应的小数组段上,这时候树形结构上场了。一个很大的数组必然可以由一个个小数组拼接而成,若定义一个最小粒度的数组长度,比如长度4,那么从宏观上看一个大数组就由一个个长度为4的小数组排队而成。

ymf604的专栏 1085

OpenHarmony南向开发:深入浅出剖析NAPI框架

NAPI的概念源自Nodejs,为了实现javascript脚本与C++库之间的相互调用,Nodejs对V8引擎的api做了一层封装,称为NAPI。

qq_39652397的博客 1484

[机器学习-回归实例] 李宏毅机器学习作业一:PM2.5 预测实例

[机器学习-回归实例] 李宏毅机器学习作业一:PM2.5 预测实例 简介   这是一个回归预测的实例,数据集来自李宏毅的《机器学习》课程的第一次作业,可以用来训练一个线性回归模型或者其他的回归模型,动手实践学习到的理论知识,在实践中去发现问题。这篇文章主要包括数据集的解释、数据的预处理过程及线性回归模型的代码实现这三个部分。由于这个数据集并不能直接使用,还需进行一些重构,为了对初学者更友好一些,我会提供重构完的可以读取后就直接使用的数据集,我也会提供 Matlab\rm MatlabMatlab 可直接使用

qq_27309515的博客 3574
上一篇: Openharmony上如何编译与运行HelloWorld
下一篇: Openharmony应用NAPI详解--进阶篇1
procedurecode
博客等级 码龄20年 3298粉丝 67原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值