鸿蒙OS开发实例:【NAPI 进阶】

本篇将会介绍另外两种集成方式:

  1. NAPI源码 + 动态库(即 .so)
  2. TS接口 + 动态库(即 .so)

Native C++应用研发概况

Native C++应用场景,总结起来就如下

  • "部分源码+动态库": 国密算法SM4已经提前被编译成了so文件,这个时候我们只需在CMakeList.txt文件中稍许配置一下,即可完成so的引用
  • “TS接口+动态库”: 国密算法SM4和NAPI接口文件均已被提前编译成了so文件,这个时候只需添加TS声明文件和配置动态库依赖

部分源码&动态库

鸿蒙OS开发 更多内容→点击 发知识更新库qr23.cn/AKFP8k在这。

生成SM4动态库

搜狗高速浏览器截图20240326151547.png

借助“全部源码”接入方式,先修改CMakeList.txt, 让其在编译时生成"sm4.so"文件

# the minimum version of CMake.
cmake_minimum_required(VERSION 3.4.1)
project(HarmonyLearn)

set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})

include_directories(${NATIVERENDER_ROOT_PATH}
                    ${NATIVERENDER_ROOT_PATH}/include)

add_library(customnapi SHARED main.cpp
                         util.cpp)

#源码生成 sm4.so
#add_library(sm4 SHARED sm4.cpp)

target_link_libraries(customnapi PUBLIC libace_napi.z.so sm4)

编译"entry"模块(Build -> Build Hap(s)/APP(s) -> Build Hap(s))

编译完成后的产物,可以在如下路径下找到

entry/build/default/intermediates/libs/default/

创建C++文件夹,导入文件

在entry主模块中的 “src/main” 路径下创建 “cpp” 文件夹,然后添加sm4动态库需要的透文件sm4.h,之后在"cpp"文件夹下创建一个"libs"文件夹,导入libsm4.so动态库

最终的路径

  • 头文件: scr/main/cpp/include/sm4.h
  • 动态库: scr/main/cpp/libs/arm64-v8a/libsm4.so, scr/main/cpp/libs/armeabi-v7a/libsm4.so

修改CMakeFile.txt

因为我们用到了提前编译好的libsm4.so, 所以在引入时和源码生成方式稍微不一样

差异

源码生成库

add_library(sm4 SHARED sm4.cpp)

预制库生成库

add_library(sm4 SHARED IMPORTED)

set_target_properties(sm4 PROPERTIES IMPORTED_LOCATION 路径/libsm4.so)

CMakeFile源文件

# the minimum version of CMake.
cmake_minimum_required(VERSION 3.4.1)
project(HarmonyLearn)

set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})

include_directories(${NATIVERENDER_ROOT_PATH}
                    ${NATIVERENDER_ROOT_PATH}/include)

add_library(customnapi SHARED main.cpp
                         util.cpp)

#设置 libsm4.so路径
set(my_lib_path ${CMAKE_CURRENT_SOURCE_DIR}/libs/)
message("my_lib_path = ${my_lib_path}${OHOS_ARCH}/")

#生成 sm4.so
add_library(sm4 SHARED IMPORTED)
set_target_properties(sm4 PROPERTIES IMPORTED_LOCATION ${my_lib_path}${OHOS_ARCH}/libsm4.so)

#链接customnapi动态库
target_link_libraries(customnapi PUBLIC libace_napi.z.so sm4)

配置应用Native编译选项

在"entry"模块中的build-profile.json5文件中,设置CMakeFist.txt路径和动态库CPU架构

编写NAPI接口

样例中main.cpp文件, 文件详情见代码库

// entry\src\main\cpp\main.cpp
// 引入N-API相关头文件。
#include "napi/native_api.h"
#include <csignal>
#include <iostream>
#include "sm4.h"
#include <sstream>
#include "util.h"

/**
 * 测试国密SM4接口: 加密
 *
 * @param env
 * @param info
 * @return
 */
static napi_value encryptBySm4(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};

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

    size_t typeLen = 0;
    napi_get_value_string_utf8(env, args[0], nullptr, 0, &typeLen);

    char *extContent = new char[typeLen + 1];
    napi_get_value_string_utf8(env, args[0], extContent, typeLen + 1, &typeLen);

    sm4 s;
    s.setType(sm4::CBC);
    s.setKey("1234567890123456");
    s.setIv("asdfghjklzxcvbnm");

    std::string originStr = extContent;

    std::string encryptData = s.encrypt(originStr);

    util k;
    std::string hexStr = k.strToHex(encryptData);

    const int length = hexStr.length();

    char *char_array = new char[length + 1];

    strcpy(char_array, hexStr.c_str());

    std::cout << "你好" << char_array;

    napi_value result;
    napi_create_string_utf8(env, char_array, length + 1, &result);

    delete[] char_array;

    return result;
}

EXTERN_C_START
// Init将在exports上挂上Add/NativeCallArkTS这些native方法,此处的exports就是开发者import之后获取到的ArkTS对象。
static napi_value Init(napi_env env, napi_value exports) {
    // 函数描述结构体,以Add为例,第三个参数"Add"为上述的native方法,
    // 第一个参数"add"为ArkTS侧对应方法的名称。
    napi_property_descriptor desc[] = {
       ......
{"encryptBySm4", nullptr, encryptBySm4, nullptr, nullptr, nullptr, napi_default, nullptr},
        ......
    };
    // 在exports这个ArkTS对象上,挂载native方法。
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    return exports;
}
EXTERN_C_END

// 准备模块加载相关信息,将上述Init函数与本模块名等信息记录下来。
static napi_module demoModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "customnapi",
    .nm_priv = ((void *)0),
    .reserved = {0},
};

// 打开so时,该函数将自动被调用,使用上述demoModule模块信息,进行模块注册相关动作。
extern "C" __attribute__((constructor)) void RegisterModule(void) {
    napi_module_register(&demoModule);
}

ets使用动态库

在ets文件中,通过import customnapi from "libcustomnapi.so"方式,即可完成引用。

开始采用国密SM4加密字符串,customnapi.encryptBySm4(“测试”)

至此,“NAPI源码 + 动态库” 方式已介绍完成

TS接口&动态库

这里假设我们已经准备好了动态库,假如有两个动态库:libcustomnapi.so 和 libc++_shared.so

生成动态库

关于生成动态库的过程,可参见 “生成SM4动态库” 部分

创建C++文件夹,导入TS接口文件

在entry主模块中的 “src/main” 路径下创建 “cpp/types/libcustomnapi” 文件夹.

  1. 创建动态库对外暴露的接口声明文件, index.d.ts
  2. 创建动态库与接口文件映射的配置文件,oh-package.json5

index.d.ts文件

export const add: (a: number, b: number) => number;
export const nativeCallArkTS: (a: object) => number;
export const passStr: (a: string) => string;
export const encryptBySm4: (a: string) => string;
export const decryptBySm4: (a: string) => string;
export const generatorMockArray: (a: number) => Array<string>;
export const getCustomObject: () => Object;

oh-package.json5

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

导入动态库

在entry主模块中创建一个"libs"文件,其路径为: entry/libs, 与 entry/src 平级

配置应用对动态库的依赖

在entry主模块中的 oh-package.json5 文件中,增加如下内容

......
"devDependencies": {
  "libcustomnapi.so": "file:./src/main/cpp/types/libcusomnapi"
},
"dependencies": {
  "libcustomnapi.so": "file:./src/main/cpp/types/libcusomnapi"
},
......

ets使用动态库

在ets文件中,通过import customnapi from "libcustomnapi.so"方式,即可完成引用。

开始采用国密SM4加密字符串,customnapi.encryptBySm4(“测试”)

至此,“TS接口&动态库” 方式已介绍完成

结尾

关于Native C++应用的所有场景已介绍结束,如果你对这方面还想进一步实践一下,可以再研究一下 "codelabs/XComponent"中的代码,找找感觉。

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-04-02 21:46:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-02 21:46:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-02 21:46:02       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-02 21:46:02       20 阅读

热门阅读

  1. MongoDB聚合运算符:$log

    2024-04-02 21:46:02       14 阅读
  2. #分布式事务Seata:理解与实践

    2024-04-02 21:46:02       12 阅读
  3. 蓝桥杯每日一题:壁画(前缀和)

    2024-04-02 21:46:02       14 阅读
  4. SpringCloud面试题——Nacos

    2024-04-02 21:46:02       14 阅读
  5. 私域流量黄金时代:SCRM赋能企业深度运营

    2024-04-02 21:46:02       11 阅读
  6. ARM_02-光控灯

    2024-04-02 21:46:02       14 阅读
  7. 【力扣】45.跳跃游戏Ⅱ

    2024-04-02 21:46:02       12 阅读
  8. NAT协议

    NAT协议

    2024-04-02 21:46:02      13 阅读
  9. 蓝桥杯刷题_day10

    2024-04-02 21:46:02       14 阅读
  10. python数据类型内置方法(部分明天补充)

    2024-04-02 21:46:02       14 阅读
  11. C语言中输入函数scanf与gets得区别

    2024-04-02 21:46:02       16 阅读