0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

教程分享!OpenHarmony之NAPI框架介绍

电子发烧友开源社区 来源:未知 2023-11-30 12:15 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

NAPI 是什么

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

wKgaomVoDXaAEIhiAACKsNK2uTI532.png

可以看到,NAPI 接口本身是 C++语言实现的,这些接口可以帮助 C++代码创建 JS 变量,或访问 JavaScript 运行环境中的 JS 变量与方法。

OpenHarmony 中的 NAPI

OpenAtom OpenHarmony(以下简称“OpenHarmony”)应用层基于 javascript 语言开发,而系统框架层则基于 C++语言。它们之间需要一个桥梁来实现两种语言代码之间的相互调用,这个桥梁就是 NAPI。

wKgaomVoDXaAIg1bAAATeJfNdak212.png

这里可能有的小伙伴有疑问了:OpenHarmony 的 NAPI 和 NodeJs 的 NAPI 是一回事吗?

应该说,OpenHarmony 系统沿用了 NAPI 的接口定义形式,但每个接口的内部实现都进行了重写。这是因为 NAPI 接口的本质是帮助 C++程序去跟 Javascript 引擎交互,因此对于不同的引擎需要有不同的实现方式。

当用户调用了 NAPI 接口 napi_create_int64(), 对于 Nodejs 而言,它会去访问 V8 引擎的 api 创建一个 js 的数字变量,而对于 OpenHarmony,则是去访问 ArkUI 框架自己的 js 引擎(ArkNativeEngine)。在 OpenHarmony 源码中搜索 napi_create_int64() 方法,你会得到一份头文件定义:third_party odesrcjs_native_api.h

以及两份不同的实现代码:

third_party
odesrcjs_native_api_v8.cc
foundationarkui
api
ative_engine
ative_api.cpp

(左右移动查看全部内容)

native_api.cpp 是 OpenHarmony 版本的 NAPI 实现,想了解内部细节的可以从这里入手:

wKgaomVoDXaAHg5vAACfZ672Y9U740.png

创建一个简单的 NAPI 工程

可以通过 DevEco Studio 的 Native C++模板创建一个包含简单 NAPI 实现的样例工程。

wKgaomVoDXaAD7m5AAA4g0WWTpI528.png

该工程自带一个 hello.cpp,实现了一个能够被 javascript 代码调用的 add()方法。

wKgaomVoDXeAZ_oNAAExaOIHWkE937.png

下面我们就基于这个简单的例子,探究一下 NAPI 框架的实现原理。

应用如何调用 NAPI 接口

应用代码导入对应的 so 库后,就可以调用该库实现的接口。

wKgaomVoDXeAQpUIAAChsVRRkG0548.png

这里我们注意到,导入日志库时使用的名称是"@ohos.hilog",应用代码如果写成 import hilog from 'libhilog.z.so' 其实也是可以成功导入的。

实际上,ArkUI 在运行时会将 @ohos.hilog 转换为 libhilog.z.so,然后到 /system/lib/module/ 目录下查找此库并加载。

系统实现的 NAPI 库都放在/system/lib/module/目录下,类似的:

  • @ohos.wifiManager 对应的是 /system/lib/module/libwifimanager.z.so;

  • @ohos.deviceInfo 对应的是 /system/lib//module/libdeviceinfo.z.so

除了系统自带的 NAPI 库,应用也可以用 C++开发自己的 NAPI 库。上面例子中 import testNapi from 'libentry.so' 导入的就是应用自己实现的。应用开发的 NAPI 库会随着应用工程一起编译打包到 hap 文件中,最终部署到/data 目录每个应用自己的文件夹下。

wKgaomVoDXeALQgHAAEoRfL6EPs348.png

NAPI 库的导入原理

我们知道,应用的 javascript 代码是由 ArkUI 的 JS 引擎解释执行的。当 JS 引擎解读 import hilog from '@ohos.hilog'; 这行代码时,会通过 dlopen() 将对应的 libhilog.z.so 加载到应用进程中。这一切是怎么做到的呢?

每个应用进程在初始化时,都会创建一个引擎实例 ArkNativeEngineImpl,我们来看一下它的构造函数

foundationarkui
api
ative_engineimplarkark_native_engine_impl.cpp

(左右移动查看全部内容)

wKgaomVoDXeAMAK5AADrkyFWTa4032.png

也就是说,每个应用进程的 JS 引擎中,都注册了一个"requireNapi"函数,当应用调用此方法时,JS 引擎就会通过 NAPI 框架的 moduleManager 类去处理 so 库的加载。moduleManager 内部最终是找到了/system/lib/module 下对应的 so 文件,并通过 dlopen()的方式加载到应用进程中。想了解细节的小伙伴可以读一下 NativeModuleManager::LoadNativeModule()方法的内部实现。

这里可能会有个疑问:应用的 javascript 代码中并没有写什么"requireNapi"的代码,只有 import xxx,怎么触发的导入处理函数?答案要到编译后的 js 代码中寻找。我们解开编译后的 hap 包,找到 ets 文件对应的 js 文件:

wKgaomVoDXeAeAuGAACFo3COaqI892.png

可以看到,index.ets 被编译成 index.js 后,import 关键字也被转为了"requireNapi",这样 JS 引擎在执行这行代码时,就会去调用注册的导入处理函数了。

wKgaomVoDXeAcE1wAACFc38EnB8472.png

C++库如何实现 JS 方法

前面解决了 JS 导 C++库的问题,下一步就是 JS 如何调用 C++库里的方法了。先说结论:一个 C++方法能否被应用调用,取决与 C++代码有没有将这个方法注册到 JS 引擎。

我们来看看 hello.cpp 是如何注册 add 方法的:

wKgaomVoDXiAJSkWAAE4E8ZHYPc725.png

我们可以从下往上看这段代码:首先是 RegisterEntryModule(void) 方法。这是 C++向 JS 引擎进行 NAPI 模块与方法注册的起始代码。注意这个方法前面有个编译修饰符 "attribute((constructor))",它的作用是指导 C++代码的编译,使得当 so 库被加载到应用进程中时,RegisterEntryModule(void) 方法就会被自动调用到。该方法通过 NAPI 接口 napi_module_register() 向 JS 引擎注册了一个 napi_module。

然后是 Init()方法。该方法实现了 Add 方法的注册。也就是告诉 JS 引擎,将 JS 符号"add" 与 C++方法"Add" 进行关联映射。这样后续当 JS 引擎解释执行 javascript 代码 "testNapi.add(2, 3)"时,就会找到 C++ Add()方法的函数地址并调用。如下图所示:

wKgaomVoDXiAfWNYAAM0UOoVFnQ341.png

方法关联调用的问题也解决了,最后就是 JS 运行环境与 C++运行环境的相互切换了。当 C++的 Add 方法被 JS 引擎调用到后,引擎会将 javascript 下发的参数变量传递给 C++。所有从 JS 运行环境传递过来的变量都是用 napi_value 类型来表示的。需要通过 NAPI 接口转为 C++语言的变量类型。详见下图每行代码的注释:

wKgaomVoDXiAcCHPAAMw9le05dg911.png

napi_value 不是一个具体的类型,它类似于 void*,表示的是 JS 变量在 JS 引擎内部存储区内的地址。需要通过对应的 NAPI 方法实现,例如:napi_get_value_int32() --- js 变量转为 c++整形 napi_get_value_string_utf8() --- js 变量转为 c++字符串 napi_get_value_bool() --- js 变量转为 c++布尔值

这些接口的具体用法和使用场景,可以参考 NodeJs 官方文档(https://nodejs.org/dist/latest-v20.x/docs/api/n-api.html)

C++程序链接 NAPI 库

OpenHarmony 的 NAPI 接口实现都封装在 libace_napi.z.so 中,C++程序编译时需链接此库。对于 DevEco Studio 应用开发的 cpp 代码,在对应的 CMakeLists.txt 中链接。该库文件在 SDK 目录下可以找到。

wKgaomVoDXiAE6tWAACZOD3pQ24204.png

对于设备侧开发,系统框架中的 C++程序,则通过 BUILD.gn 文件定义依赖关系。

wKgaomVoDXiAJKJ5AAAJs2wWfI8320.png

总结

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


更多热点文章阅读
  • 大佬分享!基于OpenHarmony操作系统无人机
  • DevEco Studio 3.1 Release | 动态共享包开发,编译更快,包更小
  • Cocos携手乐元素,《开心消消乐》成功移植OpenHarmony
  • 开源样例!基于小凌派RK2206的工地检测平台设计
  • DevEco Device Tool 3.1 Release新版本发布


原文标题:教程分享!OpenHarmony之NAPI框架介绍

文章出处:【微信公众号:电子发烧友开源社区】欢迎添加关注!文章转载请注明出处。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 电子发烧友
    +关注

    关注

    33

    文章

    584

    浏览量

    33980
  • 开源社区
    +关注

    关注

    0

    文章

    95

    浏览量

    775

原文标题:教程分享!OpenHarmony之NAPI框架介绍

文章出处:【微信号:HarmonyOS_Community,微信公众号:电子发烧友开源社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    触觉智能RK3576开发板OpenHarmony开源鸿蒙系统USB控制传输功能示例

    本文介绍OpenHarmony开源鸿蒙系统的USB控制传输功能实现及相关代码示例,基于触觉智能RK3576开发板PurplePiOH2演示。OpenHarmony的USB通信介绍实现
    的头像 发表于 09-30 16:31 1215次阅读
    触觉智能RK3576开发板<b class='flag-5'>OpenHarmony</b>开源鸿蒙系统USB控制传输功能示例

    两款搭载KaihongOS的开鸿开发板被评为“OpenHarmony 明星开发板”

    OpenHarmony
    深开鸿
    发布于 :2025年09月11日 10:10:02

    【M-K1HSE开发板免费体验】相关源码阅读和分析1-使用XComponent + Vsync 实现自定义动画

    (HarmonyOS) / OpenHarmony 原生应用 (Native App) 项目,它利用了 ArkUI 的 XComponent 组件 和 NAPI (Native API) 框架来实现高性能
    发表于 09-03 16:05

    知乎开源“智能预渲染框架” 几行代码实现鸿蒙应用页面“秒开”

    近日,知乎在Gitee平台开源了其自研的鸿蒙“智能预渲染框架”,并将该框架的Har包上架到OpenHarmony三方库中心仓。该框架在鸿蒙平台首创“智能预渲染”技术,旨在破解应用复杂页
    的头像 发表于 08-29 14:32 466次阅读
    知乎开源“智能预渲染<b class='flag-5'>框架</b>” 几行代码实现鸿蒙应用页面“秒开”

    OpenHarmony2025年度竞赛训练营重磅开启

      OpenHarmony2025年度竞赛训练营       活动介绍 OpenHarmony竞赛训练营 旨在引导高校学生进行OpenHarmony产学研用,培养更多应用型人才和产业需
    的头像 发表于 07-16 11:51 715次阅读

    第三届大会回顾第3期 | FFRT并发框架OpenHarmony中的设计与实践

    演讲嘉宾 | 黄佑钟 回顾整理 | 廖   涛 排版校对 | 宋夕明 嘉宾介绍 开发框架分论坛  黄佑钟 ,海思Kirin解决方案并行与异构计算专家。 正文内容 多任务并发能更有效地利用CPU资源
    的头像 发表于 06-21 16:53 959次阅读
    第三届大会回顾第3期 | FFRT并发<b class='flag-5'>框架</b>在<b class='flag-5'>OpenHarmony</b>中的设计与实践

    开源鸿蒙开发必备!OpenHarmony替换Full SDK全攻略

    本文介绍开源鸿蒙OpenHarmony替换FullSDK的方法,演示设备为触觉智能PurplePiOH鸿蒙开发板获取FullSD
    的头像 发表于 06-06 18:11 643次阅读
    开源鸿蒙开发必备!<b class='flag-5'>OpenHarmony</b>替换Full SDK全攻略

    贡献 OpenHarmony 库关键配置

    # 贡献 OpenHarmony 库关键配置 #自研框架#ArkUI-X#三方框架#OpenHarmony#HarmonyOS ## 创建第三方库 - 打开 DevEco Stud
    发表于 05-28 13:46

    北京迅为RK3568开发板OpenHarmony系统南向驱动开发内核HDF驱动框架架构

    北京迅为RK3568开发板OpenHarmony系统南向驱动开发内核HDF驱动框架架构
    的头像 发表于 03-11 14:13 1558次阅读
    北京迅为RK3568开发板<b class='flag-5'>OpenHarmony</b>系统南向驱动开发内核HDF驱动<b class='flag-5'>框架</b>架构

    【贝启科技BQ3568HM开源鸿蒙开发板深度试用报告】2 - 智能家居中控屏界面设计:打造便捷的家居控制体验

    设计,并探讨其在智能家居中控屏中的应用。 NAPI接口概述 NAPI接口是OpenHarmony提供的一种机制,用于在ArkTS中调用C++编写的原生模块。通过NAPI接口,开发者可以
    发表于 01-24 16:11

    迅为RK3568开发板篇OpenHarmony实操HDF驱动控制LED-编写内核 LED HDF 驱动程序

    接下来编译 LED 驱动,该驱动用于在基于华为设备框架(HDF)的系统中控制 LED 灯的开关,完整代码如下所示: 更多内容可以关注:迅为RK3568开发板篇OpenHarmony
    发表于 01-17 15:13

    AI开发框架集成介绍

    随着AI应用的广泛深入,单一框架往往难以满足多样化的需求,因此,AI开发框架的集成成为了提升开发效率、促进技术创新的关键路径。以下,是对AI开发框架集成的介绍,由AI部落小编整理。
    的头像 发表于 01-07 15:58 928次阅读

    鸿蒙原生页面高性能解决方案上线OpenHarmony社区 助力打造高性能原生应用

    Nodepool、HMrouter和DataCache 三大解决方案,并上架OpenHarmony开源社区分,分别针对应用页面滑动、跳转、首页冷启动等关键性能场景提供高效易用的工具,助力伙伴和开发者打造
    发表于 01-02 18:00

    AKI跨语言调用库神助攻C/C++代码迁移至HarmonyOS NEXT

    ,真正做到所“键”即所得。 这一创新框架的出现,正是为了解决开发者在迁移C/C++项目到HarmonyOS NEXT时面临的核心痛点。传统的NAPI接口调用复杂,学习成本高,开发者需要耗费大量精力进行适配
    发表于 01-02 17:08

    OpenHarmony程序分析框架论文入选ICSE 2025

      近日,ICSE 2025软件工程实践Track放榜,面向OpenAtom OpenHarmony(以下简称“OpenHarmony”)的ArkTS程序分析基础框架--方舟程序分析器(论文题目为
    的头像 发表于 01-02 13:41 1833次阅读
    <b class='flag-5'>OpenHarmony</b>程序分析<b class='flag-5'>框架</b>论文入选ICSE 2025