掌握DevEco Studio这一功能,高效实现ArkTS与C++胶水代码

掌握DevEco Studio这一功能,高效实现ArkTS与C++胶水代码

1、背景介绍

HarmonyOS 主要提供了ArkTS与C++作为开发语言:

  • ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript(简称TS)生态基础上做了进一步扩展,保持了TS的基本风格,同时通过规范定义强化开发期静态检查和分析,提升程序执行稳定性和性能。ArkTS适合用在高效UI界面开发场景。
  • C++以NDK(Native Development Kit)工具集的方式提供支持,NDK是HarmonyOS SDK提供的Native API、相应编译脚本和编译工具链的集合,方便开发者使用C或C++语言实现应用的关键功能。NDK只覆盖了HarmonyOS一些基础的底层能力,如C运行时基础库libc、图形库、窗口系统、多媒体、压缩库、面向ArkTS/JS与C跨语言的Node-API等,并没有提供ArkTS/JS API的完整能力。C++语言适合下方这些场景:
    • 性能敏感的场景,如游戏、物理模拟等计算密集型场景。
    • 需要复用已有C或C++库的场景。
    • 需要针对CPU特性进行专项定制库的场景,如Neon加速。

有一些能力HarmonyOS只提供了C++接口支持,比如音视频编解码等,而且我们注意到最新发布的HarmonyOS 5.0.1版本,新增的能力主要是C API,所以要挖掘HarmonyOS更多能力成为一个资深HarmonyOS工程师,ArkTS与C++混合开发是必不可少的。

ArkTS调用C++需要经过一系列复杂流程,本文主要介绍DevEco Studio提供的一键生成跨语言"胶水"代码工具帮助大家提升开发效率。

2、ArkTS调用C++方法流程

类似于Android JNI,HarmonyOS 中ArkTS调用C++方法主要是NAPI提供能力。本节以DevEco Studio新建的Native C++工程Demo为例介绍ArkTS调用C++方法流程。下图是创建Native C++工程后的代码结构图:

主要有三大部分组成:

  • types:
    • Index.d.ts:主要包含对ArkTS暴露的C++接口。
    • oh-package.json5:指定动态库名称和上面Index.d.ts文件路径。
  • CMakeLists.txt:C++代码构建脚本。
  • napi_init.cpp:C++实现代码

开发Native模块一般流程就是要实现上述对应模块。

2.1 Index.d.ts中声明C++接口

声明的函数供C++实现和ArkTS中调用

typescript 复制代码
export const add: (a: number, b: number) => number;
2.2 C++中注册和实现声明方法

首先在NAPI的Init方法中注册Index.d.ts中声明的方法:

arduino 复制代码
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

napi_property_descriptor是一个数组,可以实现多个方法。示例中字符串"add"表示Index.d.ts中声明的add方法,第三个参数Add表示C++中实现的方法名。接下来就需要实现Add方法:

ini 复制代码
static napi_value Add(napi_env env, napi_callback_info info)  
{  
    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;  
  
}

NAPI的实现方法结构是固定的,返回值必须是napi_value,参数必须是两个napi_env与napi_callback_info,方法中解析napi_callback_info具体参数信息实现具体功能。

2.3 CMakelist.txt中配置编译的动态库名称与C++源码列表

add_library指定编译输出的库名称和参与编译的C++代码列表:

scss 复制代码
add_library(entry SHARED napi_init.cpp)

这方面知识可以参考CMake构建工具相关文档:cmake.org/

2.4 ArkTS中调用声明的方法

最后,实现好后就可以在ArkTS中调用对应的方法:

csharp 复制代码
//首先导入动态库:
import testNapi from 'libentry.so';
//调用对应add方法
hilog.info(0x0000, 'testTag', 'Test NAPI 2 + 3 = %{public}d', testNapi.add(2, 3));

3、DevEco Studio 快速生成胶水代码

从上面ArkTS调用C++方法流程看流程还是有点繁琐,需要在两个文件三处地方做处理,有没有便捷的方法呢?别着急,接下来介绍今天的重头戏,DevEco Studio IDE 提供的跨语言代码编辑

DevEco Studio IDE提供了两种创建方式:

  1. Index.d.ts中编写函数声明,一键生成C++函数
  2. C++头文件编写C++函数声明,一键生成注册代码

下面分别进行详细介绍。

3.1 Index.d.ts中编写函数声明,一键生成C++函数

在Index.d.ts中声明方法后,IDE会提示错误,鼠标悬停后会有下图提示:

点击"Generate native implementation"后即可快捷生成C++中的注册代码与实现代码:

这样三处手动实现变成了一处,功能还是非常实用,提效不止三分之二。

3.2 C++头文件编写C++函数声明,一键生成注册代码

通过C++函数声明一键创建的方式,需要我们先创建一个头文件,然后在头文件中声明方法:

右键该方法,点击生成:

继续点击NAPI:

注册函数中,以及对应NAPI函数实现已经帮助我们完成生成:

Index.d.ts中的声明方法也已经帮助我们生成:

通过IDE的版主,跨语言之间的"胶水"代码编写极大的提高了效率,不得不说,DevEco Studio 提供的这块功能还是相当不错的,很为广大程序员考虑。

这里面需要注意的有三点:

  1. 快捷生成代码的头文件支持类型:.hpp,.hxx,.hh,.h;
  2. 声明的快捷生成NAPI的函数当前支持bool,int,string,void,float,double,std::array,std::vector等参数类型;
  3. 如果工程中已经创建napi_init.cpp,则会在文件的Init中追加,如果没有创建,IDE会帮助我们自动创建。

4、借助AI提升C++代码中NAPI类型转换代码书写

有了IDE提供的自动生成跨语言胶水代码已经极大的帮助我们进行Native 代码开发,但是可能还有小伙伴感觉生成的TODO中的代码也很繁琐,很多ArkTS与C++的跨语言转换代码也很模版和繁琐,有没有对应的提效办法呢? 以自动生成的add代码为例:

ini 复制代码
static napi_value Add(napi_env env, napi_callback_info info)  
{  
    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;  
  
}

需要从napi_callback_info解析两个int类型参数,完成运算后还要继续生成napi_value返回。

因为这种跨语言数据类型转换时NAPI协议,DevEco CodeGenie插件也提供了不错的支持,可以在DevEco Studio 中安装Genie插件帮助我们生成快速生成C++实现代码:

这样,几次"TAB"键后就帮我们生成差不多了,再根据我们业务逻辑实现自己代码即可。

5、总结

本文主要介绍了Native C++代码的实现步骤,以及DevEco Studio IDE提供的跨语言代码编辑工具,实现只写函数声明一键帮助我们生成对应初始化注册方法与C++实现方法,希望大家多多体验,通过工具提升我们开发效率。

相关推荐
奶油泡芙9311 小时前
Insert Digit插入数字
c++·算法
夕泠爱吃糖2 小时前
C++中如何实现多态性与性能的平衡?
开发语言·c++
文宇炽筱2 小时前
c++中<cmath>库中的各个函数
开发语言·c++
Feliz Da Vida2 小时前
union find算法 c++
开发语言·c++·算法
唐棣棣3 小时前
期末速成C++【初识C++】
开发语言·c++
走向菜鸟的菜鸟4 小时前
【HarmonyOS】关于鸿蒙原生实现红包雨效果的方案
harmonyos·arkts
比奇堡冷酷包工头5 小时前
C语言:数据类型(整型)
c语言·c++·经验分享·笔记
咔咔咔的5 小时前
3264. K 次乘运算后的最终数组 I
c++