【坚果派-坚果】Napi入门【一】 原创 精华
作者:坚果
团队:坚果派
公众号:“大前端之旅”
润开鸿技术专家,华为HDE,CSDN博客专家,CSDN超级个体,CSDN特邀嘉宾,InfoQ签约作者,OpenHarmony布道师,电子发烧友专家博客,51CTO博客专家,擅长HarmonyOS/OpenHarmony应用开发、熟悉服务卡片开发,在“战码先锋”活动中作为大队长,累计培养三个小队长,带领100+队员完成Pr的提交合入。
欢迎通过主页或者私信联系我,加入坚果派,一起学习HarmonyOS/OpenHarmony应用开发。
NAPI是什么?
NAPI(Native API)组件是一套对外接口基于Node.js N-API规范开发的原生模块扩展开发框架。
在移动应用开发中需要使用 C/C++
实现的场景有很多,比如音视频处理,图像处理等较高性能要求的场景。
OpenHarmony 提供了 NAPI 框架用于实现 JS 和 C/C++ 互相调用的能力,DevEco Studio 默认支持创建 NAPI 应用,我们今天就来创建一个NAPI 工程。
创建NAPI 工程
打开IDE,选择创建项目,选择下面的Native C++模板
点击 Next 按钮后,项目名称选择NapiHello,点击finish即可
等待项目加载完成,如果大家观察细致的话,会发现,这里面有个不同之处就是多了CPP目录
我么可以点开来看一下
该目录用来存放 cpp 的源码及相关配置文件,各文件说明如下:
- hello.cpp:index.d.ts 文件中声明的方法的 C++ 实现源码。
- CMakeLists.txt:是cmake用来生成Makefile文件需要的一个描述编译链接的脚本文件。
- index.d.ts:对 ts 提供的方法声明。
- package.json:打包的配置文件。
另外 CMakeLists.txt 文件还会在 build-profile.json5 里做配置,代码如下所示:
点击自动化签名,然后运行项目就可以
这个时候我们就可以来看一下代码内容,分析一下了
我们再来看一下index.ets的内容
运行之后,我们就可以看到
NAPI项目简述
index.d.ts解读
在 cpp 的 libentry 目录下生成了 index.d.ts 文件,它的源码如下所示:
export const 表示导出一个常量以便在其它文件中使用。add 是一个返回类型为 number
的方法,它的参数类为 number
类型。
package.json解读
在 cpp 的 libentry 目录下生成了 package.json 文件,该文件是打包的配置文件,内容如下所示:
设置 libentry.so 库和 index.d.ts 相关联,便于在 TS 文件中引入 libentry.so 时调用库中的相关方法。
CMakeLists.txt解读
CMake 是一个开源跨平台的构建工具,旨在构建、测试和打包软件,CMake 是 makefile 的上层工具,用于跨平台构建环境,生成可移植的 makefile 并简化自动动手写 makefile 的工作量,在 cpp 目录下默认生成的 CMakeLists.txt 内容如下所示:
hello.cpp解读
在 cpp 目录下默认生成的 hello.cpp 文件,源码如下所示:
hello.cpp 的代码不是很复杂,我们可以做如下拆分:
-
引入头文件
引入头文件,作用和 TS 里的 import 类似,不再详述。
-
注册napi模块
定义 NAPI 模块,类型为 napi_module 结构体,各字段说明如下:
- nm_version:nm版本号,默认值为 1。
- nm_flags:nm标记符,默认值为 0。
- nm_filename:暂不关注,使用默认值即可。
- nm_register_func:指定nm的入口函数。
- nm_modname:指定 TS 页面导入的模块名,例如:
import testNapi from 'libentry.so'
中的 testNapi 就是当前的nm_modname。 - nm_priv:暂不关注,使用默认值即可。
- reserved:暂不关注,使用默认值即可。
extern "C"
简单理解就是告诉编译器这部分代码按照 C 语言进行编译而不是 C++ 语言编译。__attribute__((constructor))
声明方法的执行时机,它表示RegisterEntryModule()
方法在main()
方法执行前执行,RegisterEntryModule()
方法内调用了napi_module_register()
方法,该方法是 NAPI 提供的模块注册方法,表示把定义的 demoModule 模块注册到系统中。 -
方法定义
Init()
方法内声明了 napi_property_descriptor 结构体,结构体的定义看第一个和第三个参数即可,第一个参数 add 表示应用层 JS 声明的方法,Add 表示 Native C++ 实现的方法,然后调用 NAPI 的 napi_define_properties() 方法将add
和Add
做个映射,最后通过 exports 变量对外导出,实现 JS 端调用 add 方法时进而调用到 C++ 的 Add() 方法。 -
方法实现
Add()
方法注释的很清楚,首先从 napi_callback_info 中读取 napi_value 类型的参数放入到 args 中,然后从 args 中读取参数并把 napi_value 类型转换成 C++ 类型后进行加操作,最后把相加的结果转换成 napi_value 类型并返回。 -
模块导入
根据前边的编译配置,cpp 目录下的源码最终打包成了 libentry.so,使用前直接引入即可。
-
方法调用
引入 libentry.so 模块后,就可以直接调用
add()
方法了。
NAPI数据类型
napi_value数据类型
OpenHarmony NAPI 将 ECMAScript 标准中定义的 Boolean、Null、Undefined、Number、BigInt、String、Symbol和 Object 这八种数据类型以及函数对应的 Function 类型统一封装成了 napi_value 类型,它是 JS 数据类型和 C/C++ 数据类型之间的桥梁,napi_value (opens new window)官网说明如下
napi_value 表示 JS 值的不透明指针,在 C/C++ 端要使用 JS 端传递的数据类型,都是通过 NAPI 提供的相关方法把napi_value转换成 C/C++ 类型后再使用,同理当需要把 C/C的数据传递给 JS 应用层也要通过 NAPI 提供的方法把 C/C 端的数据转换成 napi_value 再向上传递。
C/C++转napi_value
NAPI提供了 napi_create_ 开头的方法表示把 C/C++ 类型转换成 napi_value 类型,常见方法如下所示:
int类型转换
把 C/C++ 的 int32_t、uint32_t 以及 int64_t 类型转换成 napi_value 类型,参数说明如下:
- env:方法调用者的运行环境,包含 JS 引擎等。
- value:C/C++端的 int 类型的值。
- result:napi_value,返回给 JS 应用层的数据。
double类型转换
把 C/C++ 端的 double 类型转换成 napi_value 类型,参数说明如下:
- env:方法调用者的运行环境,包含 JS 引擎等。
- value:C/C++ 端的 double 类型的值。
- result:napi_value,返回给 JS 应用层的数据。
string类型转换
把 C/C++ 端的 char 类型转换成 napi_value 类型,参数说明如下:
- env:方法调用者的运行环境,包含 JS 引擎等。
- str:C/C++端的字符串类型的值。
- size_t:str 的长度。
- result:napi_value,返回给 JS 应用层的数据。
napi_value转C/C++
NAPI提供了 napi_get_value_ 开头的方法表示把 napi_value 转换成 C/C++ 类型,常见方法如下所示:
int类型转换
把 JS 端的 number 类型转换成 C/C++ 的对应数据类型,参数说明如下:
- env:方法调用者的运行环境,包含 JS 引擎等。
- value:JS 端传递进来的数据。
- result:接收 value 的值。
double类型转换
把 JS 端的 number 类型转换成 C/C++ 的 double 类型,参数说明如下:
- env:方法调用者的运行环境,包含 JS 引擎等。
- value:JS 端传递进来的数据。
- result:接收 value 的值。
string类型转换
把 JS 端的 string 类型转换成 C/C++ 的 char 类型,参数说明如下:
- env:方法调用者的运行环境,包含 JS 引擎等。
- value:napi_value,JS 端传递进来的数据。
- buf:char数组,用来存放napi_value中的 string 值
- bufsize:char数组长度
- result:接收 value 的值。
boolean类型转换
把 JS 端的 boolean 类型转换成 C/C++ 的 bool 类型,参数说明如下:
- env:方法调用者的运行环境,包含 JS 引擎等。
- value:JS 端传递进来的数据。
- result:接收 value 的值。
参考
Node-API
原生模块扩展开发框架:
https://gitee.com/openharmony/arkui_napi
Node_API :用于封装JavaScript能力为native插件的API,独立于底层JavaScript,并作为Node.js的一部分。
Native API中支持的标准库 :目前支持标准C库、C++库、OpenSL ES、zlib。
C常用函数库 :math.h。
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Math/sin
Cmake :管理源代码构建的工具。
很详细的整理,感谢分享
正好入门学一下
跟着标注操作很顺利
打通南北必备软件
了解下openharmony的NAPI机制