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

        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详解-CSDN博客

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

        (3)【坚果派-坚果】Napi入门_libnapi-CSDN博客

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值