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,         // 存放参数的buffernapi_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详解--进阶篇

Openharmony应用NAPI详解--基础篇相关推荐

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

    NAPI面向C++的异步接口 3.C++实现NAPI异步接口需要做到三步 同步返回结果给js/ets调用者 另起线程完成异步操作 通过回调(callback)或Promise将异步操作结果返回 4.异 ...

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

    NAPI面向C++的异步接口(promise) promise方式的处理方式 承接上文,与callback方式不同的是,promise对象由C++侧创建以返回值的方式传递回js/ets侧,promis ...

  3. bt协议详解 基础篇(上)

    bt协议详解 基础篇(上) 最近开发了一个免费教程的网站,产生了仔细了解bt协议的想法,所以写了这一篇文章,后续还会写一些关于搜索和索引的东西,都是在开发这个网站的过程中学习到的技术,敬请期待. 1 ...

  4. iOS开发 - OC - block的详解 - 基础篇

    深入理解oc中的block 苹果在Mac OS X10.6 和iOS 4之后引入了block语法.这一举动对于许多OC使用者的编码风格改变很大.就我本人而言,感觉block用起来还是很爽的,但一直以来 ...

  5. 物联网之MQTT协议详解基础篇(一)—— MQTT介绍

    MQTT: The Standard for IoT Messaging 开场白 大概是这么个背景 比如小米智能家居目前是这么个流程: 物联网设备通过家里的wifi连接到外网服务器 在外网通过米家ap ...

  6. DNS服务器详解--------基础篇

    1.DNS介绍 域名服务器(DomainNameServer).在Internet上域名与IP地址之间是一一对应的,域名虽然便于人们记忆,但机器之间只能互相认识IP地址,它们之间的转换工作称为域名解析 ...

  7. Linux使用详解(进阶篇)

    文章目录 Linux使用详解(进阶篇) 1.Linux目录说明 2.操作防火墙 3.ulimit命令和history命令 4.RPM和Yum的使用 5.设置系统字符集 6.vi & vim编辑 ...

  8. 分布式系统详解--基础知识(概论)

                           分布式系统详解--基础知识(概论) 一. 引言         由于网上介绍的分布式的系统讲解并没有多少,所以在这儿就希望可以写一套系统的分布式的详解,未 ...

  9. [转帖]前端-chromeF12 谷歌开发者工具详解 Sources篇

    前端-chromeF12 谷歌开发者工具详解 Sources篇 原贴地址:https://blog.csdn.net/qq_39892932/article/details/82498748 cons ...

最新文章

  1. Qt中openGL的四个重要事件(initializeGL() resizeGL() paintGL() pdateGL())调用规则
  2. 机器学习笔记(5) KNN算法
  3. CSS3中背景的四个新的属性
  4. 聊下 git 使用前的一些注意事项
  5. hibernate简单应用
  6. extjs 网站首页table布局,秀一下
  7. 机器学习课程笔记【三】广义线性模型(2)-构建广义线性模型
  8. 删除exchange误发邮件
  9. 解决notepad++ php代码美化
  10. Linked list
  11. arg min什么意思
  12. 什么叫SOC-新能源充电桩
  13. 路由器级联方式(二级路由为例)
  14. mvn No proxies configured downloading directly
  15. 全返模式是怎样玩的?解析购盈利模式
  16. 1.数组简介:什么是数组???数组有哪四要素???
  17. p光圈和dc光圈的区别_为什么光圈优先模式这么好?
  18. CSDN盲盒中奖MacBook Surprise
  19. 来自澜舟科技创始人周明的一封信
  20. 推荐一个免费好用的虚拟机软件

热门文章

  1. OneDrive的申请与使用
  2. java实现pdf的生成下载打印,java生成pdf电子账单,java生成pdf合同模板
  3. docker-compose up:ERROR: Encountered errors while bringing up the project.錯誤及解決方式
  4. 2023版golang面试题100道(map)
  5. Measurement Studio​ 2019 R3
  6. STM32之ADC的理解及运用
  7. RxJava2 Flowable debounce(过滤操作符)去重复操作
  8. 腾讯企业邮箱开通过程中需要添加那些域名解析?
  9. 台灯有必要买AA级的吗?精选专业护眼的国AA级台灯
  10. 从零开始用Python搭建Socket服务器(初篇)