Advertisement

OpenHarmony ArkUI实战开发-NAPI方法扩展

阅读量:

在前三章节中, 笔者简要概述了NAPI工程并对其生成的源码进行了初步介绍. 在本章, 笔者在此基础上进一步阐述了NAPI工程的相关内容, 并新增了一个计算MD5的方法md5().

声明md5方法

在文件index.d.ts中定义一个md5()函数,并使其接受一个字符串类型的参数,并返回同样为字符串类型的值表示该字符串经过MD5计算后的结果

复制代码
    export const add: (a: number, b: number) => number;
    
    // 声明 md5 方法
    export const md5: (value: string) => string;

映射C++方法

在第1-3节中所述的知识中可知,在C++端实现时需要对两端的方法进行映射设置。因此,在hello.cpp文件的Init()方法内将MD5方法映射至C++中的Md5()函数即可完成跨端绑定配置。示例代码如下所示:

复制代码
    static napi_value Init(napi_env env, napi_value exports)
    {
    napi_property_descriptor desc[] = {
      { "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr },
      // 设置JS的md5()方法的C++实现为Md5()方法,其它参数默认即可
      { "md5", nullptr, Md5, nullptr, nullptr, nullptr, napi_default, nullptr }
    };
    
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    return exports;
    }

实现C++代码

Init() 方法中配置了 C++ 的 Md5() 方法后,需要实现 Md5() 方法,样例代码如下所示:

复制代码
    static napi_value Md5(napi_env env, napi_callback_info info) {
    
    // 1、从info中取出JS传递过来的参数放入args
    size_t argc = 1;
    napi_value args[1] = { nullptr };
    if (napi_ok != napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)) {
        napi_throw_error(env, "-1000", "napi_get_cb_info error");
        return nullptr;
    }
    
    // 2、获取参数的类型
    napi_valuetype stringType;
    if (napi_ok != napi_typeof(env, args[0], &stringType)) {
        napi_throw_error(env, "-1001", "napi_typeof error");
        return nullptr;
    }
    
    // 3、如果参数为null,则抛异常
    if (napi_null == stringType) {
        napi_throw_error(env, "-1002", "the param can't be null");
        return nullptr;
    }
    
    // 4、获取传递的string长度
    size_t length = 0;
    if (napi_ok != napi_get_value_string_utf8(env, args[0], nullptr, 0, &length)) {
        napi_throw_error(env, "-1003", "napi_get_value_string_utf8 error");
        return nullptr;
    }
    
    // 5、如果传递的是"",则抛异常
    if (length == 0) {
        napi_throw_error(env, "-1004", "the param length invalid");
        return nullptr;
    }
    
    // 6、读取传递的string参数放入buffer中
    char* buffer = new char[length + 1];
    if (napi_ok != napi_get_value_string_utf8(env, args[0], buffer, length + 1, &length)) {
        delete[] buffer;
        buffer = nullptr;
        napi_throw_error(env, "-1005", "napi_get_value_string_utf8 error");
        return nullptr;
    }
    
    // 7、模拟MD5加密操作,直接给传递进来的string后追加[NAPI]
    std::string str = buffer;
    str = str + "[NAPI]";
    
    // 8、把C++数据转成napi_value
    napi_value value = nullptr;
    const char* md5 = str.c_str();
    if (napi_ok != napi_create_string_utf8(env, md5, strlen(md5), &value)) {
        delete[] buffer;
        buffer = nullptr;
        napi_throw_error(env, "-1006", "napi_create_string_utf8 error");
        return nullptr;
    }
    
    // 9、资源清理
    delete[] buffer;
    buffer = nullptr;
    
    // 返回 value
    return value;
    }

对于Md5()方法而言其详细说明极为清晰:
首先从napi_callback_info中提取接收的数据并将其存入变量args中;
然后确定输入数据的数据类型;
接着检查输入数据类型是否为空若为空则抛出异常;
后续获取输入数据的具体长度;
若接收的数据为空字符串则抛出异常;
根据输入数据长度读取实际数据存入缓冲区中;
模拟MD5操作后直接在尾部追加[NAPI]字符串;
将C++类型转换为napi_value类型完成后续操作;
最后释放相关资源并返回计算结果

📢:读取 string 时先读取参数的长度,再读取内容。

测试C++方法

基于 Md5() 方法的实现中存在特定限制条件。具体而言,在函数执行时将不允许接收 null 类型或空字符串的数据类型作为输入,并且若输入有效值则会触发异常。进而可以验证以下三种情况:正常输入参数、传入 null 值以及提供空字符串参数。样例代码如下所示:

复制代码
    import testNapi from 'libentry.so'
    
    @Entry @Component struct Index {
    
      @State message: string = 'Hello,OpenHarmony'
    
      build() {
    Column({space: 10}) {
    
      Text(this.message)
        .fontSize(20)
    
      Button("正常参数")
        .onClick(() => {
          this.message = testNapi.md5("Hello, OpenHarmony")
        })
    
      Button("null参数")
        .onClick(() => {
          this.message = testNapi.md5(null);
        })
    
      Button("\"\"参数")
        .onClick(() => {
          this.message = testNapi.md5("");
        })
    }
    .padding(10)
    .width('100%')
    .height("100%")
      }
    }

点解 正常参数 按钮,样例运行结果如下所示:

点击 null参数 测试异常情况,异常日志如下:

复制代码
    02-28 23:50:56.176 2093-2093/com.example.oh_0400_napi E C03f00/ArkCompiler: [default] Call:1307 occur exception need return
    02-28 23:50:56.177 2093-2093/com.example.oh_0400_napi E C03900/Ace: [jsi_base_utils.cpp(ReportJsErrorEvent)-(0)] summaryBody:
    02-28 23:50:56.177 2093-2093/com.example.oh_0400_napi E C03900/Ace: Lifetime: 0.000000s
    02-28 23:50:56.177 2093-2093/com.example.oh_0400_napi E C03900/Ace: Js-Engine: ark
    02-28 23:50:56.177 2093-2093/com.example.oh_0400_napi E C03900/Ace: page: pages/Index.js
    02-28 23:50:56.177 2093-2093/com.example.oh_0400_napi E C03900/Ace: Error message: the param can't be null
    02-28 23:50:56.177 2093-2093/com.example.oh_0400_napi E C03900/Ace: SourceCode:
    02-28 23:50:56.177 2093-2093/com.example.oh_0400_napi E C03900/Ace: this.message = testNapi.md5(null);
    02-28 23:50:56.177 2093-2093/com.example.oh_0400_napi E C03900/Ace: ^
    02-28 23:50:56.177 2093-2093/com.example.oh_0400_napi E C03900/Ace: Stacktrace:
    02-28 23:50:56.177 2093-2093/com.example.oh_0400_napi E C03900/Ace: at anonymous (/ets/pages/Index.ets:20:26)

小结

本节中,在前三小节的基础上完成了C++端md5()函数的开发,并使JS端能够调用此md5()函数。此md5()函数模拟了从JS到C++的数据传递过程,并旨在演示JS与C++之间的接口调用机制。下一小节中将进一步讲解如何引入第三方库以实现真正的MD5计算功能。

如果想更深入的学习 OpenHarmony 开发的内容,可以参考以下学习文档:

OpenHarmony 开发环境搭建:https://qr18.cn/CgxrRy

对OpenHarmony源代码深入解析:https://qr18.cn/CgxrRy

  • 配置开发环境
  • Windows 系统下的开发环境配置
  • Ubuntu 系统的开发环境配置
  • Linux 和 Windows 系统间的文件共享管理
  • ……

系统架构分析:https://qr18.cn/CgxrRy

  • 建立子系统模块
    • 设计启动流程方案
    • 实现Subsystems功能
    • 开发分布式任务管理单元
    • 实现数据传输管理模块
    • 集成驱动功能模块
    • ……

OpenHarmony 设备开发学习手册:https://qr18.cn/CgxrRy

OpenHarmony面试题(内含参考答案):https://qr18.cn/CgxrRy

全部评论 (0)

还没有任何评论哟~