[经验分享] aki::Value 介绍

深开鸿_苟晶晶 显示全部楼层 发表于 2025-1-22 17:40:04

OpenHarmony 作为一个面向物联网和多设备协同的操作系统,提供了强大的跨语言开发支持。Aki 是一个专为 OpenHarmony 平台设计的开发框架,它封装了 Napi 接口,简化了 JavaScript 和 C/C++ 之间的互操作。aki::Value 是 Aki 框架中的一个核心类,它封装了 JavaScript 值的表示和操作,使得开发者可以在 C++ 中轻松处理 JavaScript 数据类型。

功能特性

aki::Value 提供了一系列功能,用于操作和转换 JavaScript 值。以下是其主要功能:

  1. 类型转换

    • aki::Value 提供了模板函数 As<T>(),用于将 JavaScript 值转换为 C++ 中的指定类型。这种类型转换功能使得开发者可以轻松地在 C++ 中处理来自 JavaScript 的数据。例如,可以将 JavaScript 的布尔值、数字或字符串转换为 C++ 的 boolintstd::string
    bool jsBool = value.As<bool>(); // 将 JS 对象 value 转化为 bool
    int jsInt = value.As<int>(); // 将 JS 对象 value 转化为 int
    std::string jsString = value.As<std::string>(); // 将 JS 对象 value 转化为 string
  2. 属性访问和设置

    • aki::Value 支持通过下标运算符 operator[] 访问 JavaScript 对象的属性或数组元素。此外,还可以通过 Set 方法为对象设置属性。这种操作方式使得 C++ 代码可以像操作本地对象一样操作 JavaScript 对象。
    aki::Value value = aki::Value::NewObject(); // 创建一个新的 JS 对象
    value.Set("name", "aki"); // 设置属性 name 为 "aki"
    std::string name = value["name"].As<std::string>(); // 获取属性 name
  3. 方法调用

    • aki::Value 提供了 CallMethod 方法,用于调用 JavaScript 对象的成员函数。这使得开发者可以在 C++ 中直接调用 JavaScript 中定义的方法,从而实现复杂的业务逻辑。
    value.CallMethod("push", "jsbind"); // 调用 JS 数组的 push 方法
  4. 创建对象

    • aki::Value::NewObject 是一个静态方法,用于创建一个新的 JavaScript 对象。这使得开发者可以在 C++ 中动态创建 JavaScript 对象,并对其进行操作。
    aki::Value obj = aki::Value::NewObject(); // 创建一个新的 JS 对象
    obj.Set("key", "value"); // 设置属性
  5. 类型检查

    • aki::Value 提供了一系列方法,用于检查 JavaScript 值的类型,例如 IsUndefinedIsNullIsBoolIsNumberIsString 等。这些方法可以帮助开发者在运行时验证数据类型,从而提高代码的健壮性。
    if (value.IsUndefined()) {
        std::cout << "Value is undefined" << std::endl;
    }
  6. 全局对象访问

    • aki::Value::FromGlobal 方法允许从 JavaScript 的全局对象 globalThis 中获取指定名称的属性。这使得开发者可以访问全局定义的函数或对象,例如 JSONconsole
    aki::Value json = aki::Value::FromGlobal("JSON");
    json["stringify"](obj); // 调用 JSON.stringify 方法

应用场景

aki::Value 的设计目标是简化 JavaScript 和 C/C++ 之间的互操作,因此它在多种场景中都非常有用:如UI开发。在 OpenHarmony 应用开发中,aki::Value 可以用于从 C++ 后端动态更新 JavaScript 前端的 UI。例如,开发者可以在 C++ 中创建一个 JavaScript 对象,并将其传递给前端代码,从而实现数据绑定。这种能力使得开发者可以利用 C++ 的高性能处理能力,同时结合 JavaScript 的灵活性来构建动态的用户界面。

aki::Value uiData = aki::Value::NewObject();
uiData.Set("title", "Hello, Aki!");
uiData.Set("message", "This is a dynamic message from C++.");

使用示例

为了更好地理解 aki::Value 的实际应用,以下是一个完整的示例,展示了如何在 OpenHarmony 应用中使用 aki::Value 进行跨语言交互。

.d.ts文件声明

export const ConvertToString: (a: object | number | string | boolean | null) => string;

.ets文件调用

let res = '';
let strArray: string[] = ['aki', 'jsbind'];
res = testNapi.ConvertToString(strArray);
console.log('[AKi] ConvertToString res1:' + res);
res = testNapi.ConvertToString(9);
console.log('[AKi] ConvertToString res2:' + res);
res = testNapi.ConvertToString(false);
console.log('[AKi] ConvertToString res2:' + res);
res = testNapi.ConvertToString('gaga');
console.log('[AKi] ConvertToString res3:' + res);
res = testNapi.ConvertToString(null);
console.log('[AKi] ConvertToString res4:' + res);

.cpp文件

#include <aki/jsbind.h>
#include "napi/native_api.h"

std::string ConvertToString(aki::Value obj) {
    if (obj.IsNull()) {  // 判断是否为空
        return "null value";
    } else if (obj.IsArray()) { // 判断是否是数组
        // 调用 JS 数组的 push 方法
        obj.CallMethod("push", "from C++");
        // obj[0].As<std::string>() 将 JS 对象value转换为c++ string
        AKI_LOG(INFO) << "akiTest obj is array, obj[0]: "<< obj[0].As<std::string>();
        AKI_LOG(INFO) << "akiTest obj is array, obj[1]: " << obj[1].As<std::string>();
        AKI_LOG(INFO) << "akiTest obj is array, obj[2]: " << obj[2].As<std::string>();
        // 从 JavaScript 的全局对象 `globalThis` 中获取指定名称的属性(这里调用JSON.stringify)
        aki::Value strObj = aki::Value::FromGlobal("JSON")["stringify"](obj);
        return strObj.As<std::string>();
    } else if (obj.IsBool()) { // 判断是否是bool类型
        return obj.As<std::string>();
    } else if (obj.IsNumber()) { // 判断是否是number类型
        return obj.As<std::string>();
    } else if (obj.IsString()) { // 判断是否是string类型
        // 创建一个新的 JS 对象
        aki::Value val = aki::Value::NewObject();
        // 调用Set设置属性
        val.Set("name", obj.As<std::string>());
        aki::Value strObj = aki::Value::FromGlobal("JSON")["stringify"](val);
        return strObj.As<std::string>();
    }
}

// Step 1 注册 AKI 插件
JSBIND_ADDON(hello) // 注册 AKI 插件名: 即为编译*.so名称,规则与NAPI一致
// Step 2 注册 FFI 特性
JSBIND_GLOBAL() {
    // Step 3 注册 ConvertToString 方法
    JSBIND_FUNCTION(ConvertToString);
}

总结

aki::Value 是 Aki 框架中的一个关键组件,它为 JavaScript 和 C/C++ 之间的互操作提供了强大的支持。通过提供类型转换、属性访问、方法调用等功能,aki::Value 使得开发者可以在 C++ 中轻松处理 JavaScript 数据,从而实现高效的跨语言开发。

©著作权归作者所有,转载或内容合作请联系作者

您尚未登录,无法参与评论,登录后可以:
参与开源共建问题交流
认同或收藏高质量问答
获取积分成为开源共建先驱

Copyright   ©2025  OpenHarmony开发者论坛  京ICP备2020036654号-3 |技术支持 Discuz!

返回顶部