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

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

本文深入解析OpenHarmony中NAPI的开发流程,包括cpp文件夹结构、CMakeLists.txt配置、NAPI函数定义与注册,及在ETS/TS文件中调用NAPI函数的方法。

        NAPI篇【1】中,讲解如何创建一个支持NAPI的OpenHarmony工程,其中有一个步骤是在OpenHarmony工程添加Harmony的NAPI工程中的cpp文件夹。cpp文件夹包含支持NAPI所需要的c/c++源码、接口导出文件以及编译文件等。本文将进行详解其中各文件的作用,帮助熟悉NAPI的开发。

        本文基于笔者的开发经验和网上参考资料汇集而成,笔者也处于学习阶段,如有错误,欢迎指正。

一、cpp文件夹——基础文件

        1、cpp文件夹基本内容

        通过NAPI模板新建工程,cpp文件夹内容全展开,如下图所示。

        2、cpp的一级目录文件

         如下图所示,cpp的一级目录下有hello.cpp、CMakeLists.txt 和一个二级目录types。

        (1)CMakeLists.txt 文件

        CMakeLists.txt是cmake用来生成Makefile文件的一个描述编译链接的脚本文件。该文件的基本内容行注释如下所示:

#CMake的最低版本要求
#默认即可
cmake_minimum_required(VERSION 3.4.1)    
 
# 用函数project(demo)指定的项目名称,可自行设置,这里变量的值为“napi”
project(napi)           

#设置环境变量,设置库文件的输出地址。
#CMAKE_CURRENT_SOURCE_DIR:当前处理的CMakeLists.txt文件所在目录
#默认即可
set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})


#给工程添加头文件,会为当前CMakeLists.txt的所有目标,
#以及之后添加的所有子目录的目标添加指定头文件搜索路径。
#默认即可
include_directories(${NATIVERENDER_ROOT_PATH}
                    ${NATIVERENDER_ROOT_PATH}/include)

add_library(entry SHARED hello.cpp)   
#将源文件hello.cpp生成动态库文件,若有多个cpp文件,需要在此添加,以便生成动态库文件
# 生成目标库文件libentry.so,entry表示最终的库名称,SHARED表示生成的是动态链接库,
#////////////////////////////////////////////////////
#add_library(生成的库名称 STATIC/SHARED 源文件1.cpp 源文件2.cpp)
#将源文件生成 静态/动态 库文件 
#STSTIC 表示静态库最终会编入到可执行文件中
#SHARED(常见参数)表示动态库(又称共享库)方式
#////////////////////////////////////////////////////

target_link_libraries(entry PUBLIC libace_napi.z.so)
# 把libentry.so链接到libace_napi.z.so上
#/////////////////////////////////////////////
#target_link_libraries (库/可执行文件 library1 library2 ...)
#将目标文件(为库或者可执行文件)与库文件进行链接
#libace_napi.z.so库,默认即可
#/////////////////////////////////////////////

        CMakeLists.txt 文件需要在 build-profile.json5 文件里做配置声明,代码如下所示,对应 NAPI篇【1】中的   二、2、(3)步。

{
  "apiType": 'stageMode',
  "buildOption": {
//在buildOption配置项中
//声明添加NAPI的编译目标,对CMakeLists.txt编译脚本进行声明执行
    "externalNativeOptions": {
      "path": "./src/main/cpp/CMakeLists.txt",
      "arguments": "",
      "cppFlags": "",
    }
/////////////////////////////////////////////////////////
  },
  "targets": [
    {
      "name": "default"
    },
    {
      "name": "ohosTest",
    }
  ]
}

        (2).cpp源文件

        在cpp文件夹的一级目录文件下,可以有多个.cpp源代码文件,比如,加一个fun.cpp文件,这些文件用来实现某一功能,带需要在CMakeLists.txt 文件中,add_library(生成的库名称 STATIC/SHARED 源文件1.cpp 源文件2.cpp)这一函数中进行声明,方便参与生成库文件。

        在cpp文件夹的一级目录文件下,还以包含.h的头文件,方便多个.cpp文件的编写,相互调用。如下图所示:

        (3) NAPI函数的定义与注册(hello.cpp解读)

        利用NAPI模板生成的工程中,默认生成的hello.cpp文件中包含了NAPI函数编写、定义与注册,文本借助hello.cpp文件的解读,来梳理。(NAPI函数的编写,详见NAPI篇【3】)

        cpp 目录下默认生成的 hello.cpp 文件,源码如下所示:

#include "napi/native_api.h"

static napi_value Add(napi_env env, napi_callback_info info)
{
    size_t requireArgc = 2;
    size_t argc = 2;
    napi_value args[2] = {nullptr};

    napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);

    napi_valuetype valuetype0;
    napi_typeof(env, args[0], &valuetype0);

    napi_valuetype valuetype1;
    napi_typeof(env, args[1], &valuetype1);

    double value0;
    napi_get_value_double(env, args[0], &value0);

    double value1;
    napi_get_value_double(env, args[1], &value1);

    napi_value sum;
    napi_create_double(env, value0 + value1, &sum);

    return sum;

}

EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports)
{
    napi_property_descriptor desc[] = {
        { "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr }
    };
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    return exports;
}
EXTERN_C_END

static napi_module demoModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "entry",
    .nm_priv = ((void*)0),
    .reserved = { 0 },
};

extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
{
    napi_module_register(&demoModule);
}
         (3.1)注册napi模块
static napi_module demoModule = {
    .nm_version =1,//nm_version:nm版本号,默认值为 1。
    .nm_flags = 0,//nm标记符,默认值为 0。
    .nm_filename = nullptr,//暂不关注,使用默认值即可。
    .nm_register_func = Init,//指定nm的入口函数,即napi定义模块
    .nm_modname = "entry",//指定 TS 页面导入的模块名,例如:`import testNapi from 'libentry.so'` 中的 testNapi 
  //就是当前的nm_modname。
    .nm_priv = ((void*)0),//暂不关注,使用默认值即可。
    .reserved = { 0 },//暂不关注,使用默认值即可。
};

extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
{
    napi_module_register(&demoModule);
}

//extern "C" 简单理解就是告诉编译器这部分代码按照 C 语言进行编译而不是 C++ 语言编译。
//__attribute__((constructor)) 声明方法的执行时机,它表示 RegisterEntryModule() 方法在 main() 
//方法执行前执行, RegisterEntryModule() 方法内调用了 napi_module_register() 方法,该方法是 
//NAPI 提供的模块注册方法,表示把定义的 demoModule 模块注册到系统中。
        (3.2)定义napi模块
EXTERN_C_START   //开始标志
static napi_value Init(napi_env env, napi_value exports)  //Init定义模块名
{
    napi_property_descriptor desc[] = {
  //需要引出的NAPI功能函数,这以Add函数为例,"add"对应 libentry 目录下index.d.ts 文件中
   //export const add: (a: number, b: number) => number;导出的函数名
//"add"自定义函数名,用于ets调用,注意与index.d.ts 文件中导出名一致;Add注册定义的函数名。
        { "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr }
//...
//定义导出的函数可以有多个
    };
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    return exports;
}
EXTERN_C_END    //结束标志

3、二级目录types

    (1) 目录libentry基本内容

        目录types包含有一个三级目录libentry

4、三级目录libentry

      (1)目录libentry基本内容

        目录libentry包含有文件index.d.ts和oh-package.json5

        (2)index.d.ts文件

        libentry 目录下生成了 index.d.ts 文件,用来声明要导出的NAPI函数,它的源码如下所示:

export const add: (a: number, b: number) => number;

        export const 表示导出一个常量以便在其它文件中使用。add 是一个返回类型为 number 的方法,它的参数类为 number 类型。

        (3)oh-package.json5文件

        libentry目录下生成了 package.json 文件,该文件是打包的配置文件,内容如下所示:

{
  "name": "libentry.so",
  "types": "./index.d.ts",
  "version": "",
  "description": "Please describe the basic information."
}

        设置 libentry.so 库和 index.d.ts 相关联,便于在 TS 文件中引入 libentry.so 时调用库中的相关方法。添加了d.ts模块,要想被ets在静态时检查到,需要配置entry/oh-package.json5下配置dependencies,对应NAPI篇【1】中的   二、2、(4)步。

二、NAPI函数的调用

        1、模块导入

        根据前边的编译配置,cpp 目录下的源码最终打包成了 libentry.so,因此,在ets或ts文件中使用前直接引入即可。例如:

import testNapi from 'libentry.so'

        2、函数调用

        引入 libentry.so 模块后,就可以直接调用在index.d.ts文件声明的NAPI函数,填入相应的参数即可,例如调用 add() 函数:

 

        参考链接:

        (1)CMakeLists.txt详解-优快云博客

        (2)CMakeLists.txt常用指令总结与练习_创建cmakelists.txt.指令-优快云博客

        (3)【坚果派-坚果】Napi入门_libnapi-优快云博客

        (4)openHarmony使用Napi开发样例_napi 中如何引入 静态库-优快云博客

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

相关推荐

OpenHarmony NAPI 使用Cmake 编译C++ .so 并ets调用

因此,我们公司也要求,所有产品的都需要支持开源鸿蒙OpenHarmony。3.2.1 创建工程之后,编译整个工程,默认会有一个cpp 文件,并且生成一个默认 libentry.so 文件,文件在build -> intermediates->cmake->default->obj->arm-v8a->libentry.so。设置 libentry.so 库和 index.d.ts 相关联,便于在其他 TS 文件中引入 libentry.so 时调用库中的相关方法,可以跳转到 .ts 接口的声明。

gd6321374的专栏 1848

openHarmony使用Napi开发样例

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

m0_49071631的博客 2910

OpenHarmony实战—— 手撕 NAPI框架

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

xianglizaibie的博客 753

Openharmony应用NAPI详解--基础篇

NAPI应用 Openharmony

流风的专栏 1万+

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

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

m0_70748458的博客 2124

鸿蒙5.0【OpenHarmony】NAPI框架

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

2401_82772199的博客 1663

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

鸿蒙开发napi系列学习高阶篇——通过IDE集成C/C++三方库并开发napi接口

应用在调用系统固件集成的C/C++三方库时,可能会由于系统固件集成端与IDE的NDK中libc++版本不一致导致调用失败,而且系统固件集成的C/C++三方库对于应用的调式也很不友好,需要多方编译调试,很不方便。因此本文将通过在IDE上适配openjpeg 三方库为例介绍IDE上适配一个C/C++三方库的具体流程。根据原生库的测试用例,我们封装2个测试用例接口} J2K_Info;

m0_70748458的博客 1991

OpenHarmony之NAPI框架

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

adaedwa187545的博客 1183

OpenHarmony 实战开发之NAPI框架介绍

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

m0_70748458的博客 838

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

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

m0_70748458的博客 1246

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

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

qq_39652397的博客 1484

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

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

Devlin_的博客 1718

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

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

2501_91726491的博客 1072

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

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

liuhaojiabin的博客 833

鸿蒙开发之NAPI框架解析

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

android__bye的博客 920
上一篇: NAPI篇【1】——如何创建含NAPI的OpenHarmony工程
下一篇: NAPI篇【3】——如何编写一个NAPI函数
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值