HarmonyOS 鸿蒙Next:从ArkTs向Native传复杂参数HashMap的方法

发布于 1周前 作者 yuanlaile 来自 鸿蒙OS

HarmonyOS 鸿蒙Next:从ArkTs向Native传复杂参数HashMap的方法 从ArkTs向Native怎样传复杂参数HashMap

3 回复

1
功能场景描述及使用场景

现实场景中,存在这样一种场景,在ArkTS层定义的List变量,从ArkTs向Native C++层传递HashMap数据时,如何在nativeC++层获取到呢。

2
使用的OS能力相关的核心API

napi_get_named_property
napi_call_function

3
核心代码解释

Index.ets文件向C++层传递HashMap数据:

build() {
  Row() {
    Column() {
      Text(this.message)
        .fontSize(50)
        .fontWeight(FontWeight.Bold)
        .onClick(() => {
          hilog.info(0x0000, 'testTag', 'Test NAPI 2 + 3 = %{public}d', testNapi.add(2, 3));
          let mapB: HashMap<string, string> = new HashMap();
          mapB.set('key_1', 'value_1');
          mapB.set('key_2', 'value_2');
          mapB.set('key_3', 'value_3');
          testNapi.putMap(mapB);
        })
    }
    .width('100%')
  }
  .height('100%')
}

C++层获取HashMap数据:

static std::string value2String(napi_env env, napi_value value) {
    size_t stringSize = 0;
    napi_get_value_string_utf8(env, value, nullptr, 0, &stringSize); // 获取字符串长度
    std::string valueString;
    valueString.resize(stringSize + 1);
    napi_get_value_string_utf8(env, value, &valueString[0], stringSize + 1, &stringSize); // 根据长度传换成字符串
    return valueString;
}

// nextResult.done 返回是否迭代下一个节点
static bool nextDone(napi_env env, napi_value nextResult) {
    napi_value done = NULL;
    napi_get_named_property(env, nextResult, "done", &done);
    bool isDone = false;
    napi_get_value_bool(env, done, &isDone);
    return isDone;
}

// nextResult<string>.value 获取当前迭代节点的值
static std::string nextValue(napi_env env, napi_value nextResult) {
    napi_value value = NULL;
    napi_get_named_property(env, nextResult, "value", &value);
    return value2String(env, value);
}

// map.get(key) 根据key从map中取value
static std::string getValueByKey(napi_env env, napi_value map, std::string key) {
    napi_value mapKey, mapValue, getFun;
    napi_create_string_utf8(env, key.c_str(), NAPI_AUTO_LENGTH, &mapKey);
    napi_get_named_property(env, map, "get", &getFun);
    napi_call_function(env, map, getFun, 1, &mapKey, &mapValue);
    return value2String(env, mapValue);
}

static napi_value ts_putMap(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);
    napi_value map = args[0];
    napi_value size = NULL;
    napi_get_named_property(env, map, "length", &size);
    int32_t sizeSize = 0;
    napi_get_value_int32(env, size, &sizeSize);
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, LOG_TAG, "ts_putMap map.length = %d", sizeSize);
    napi_value keysFun, iterableIterator = NULL;
    napi_get_named_property(env, map, "keys", &keysFun);
    napi_call_function(env, map, keysFun, 0, NULL, &iterableIterator); // 拿到map的迭代器
    napi_value nextFun, nextResult;
    napi_get_named_property(env, iterableIterator, "next", &nextFun);
    napi_call_function(env, iterableIterator, nextFun, 0, NULL, &nextResult);
    while (!nextDone(env, nextResult)) {
        std::string mapKeyString = nextValue(env, nextResult);
        std::string mapValueString = getValueByKey(env, map, mapKeyString);
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, LOG_TAG, "ts_putMap while::nextVal = %s - %s",
                     mapKeyString.c_str(), mapValueString.c_str());
        napi_call_function(env, iterableIterator, nextFun, 0, NULL, &nextResult);
    }
    return nullptr;
}

EXTERN_C_START

static napi_value Init(napi_env env, napi_value exports) {
    napi_property_descriptor desc[] = {
        {"putMap", nullptr, ts_putMap, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"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

更多关于HarmonyOS 鸿蒙Next:从ArkTs向Native传复杂参数HashMap的方法的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


思路1:将HashMap处理成ArrayBuffer传递给Native层。缺点是数据量大需要注意使用非主线程处理但又由于线程内存隔离,有些麻烦,有些数据可能也不好转为ArrayBuffer。

思路2:封装混合对象,其包含上层的HashMap及一个Native层对象,对HashMap进行数据组装时,同时给Native层Map对象组装数据。传入Native层使用时仅需要传入Native层对象指针即可。(空间换时间)

思路3:作为object传入Native层,在Native层调用ArkTs方法获取数据。(时间换空间)

在HarmonyOS(鸿蒙)系统中,从ArkTs(Ark TypeScript)向Native(原生代码)传递复杂参数如HashMap,可以通过特定的接口和序列化机制来实现。以下是一个简要的方法说明:

ArkTs端可以通过JSON或其他序列化格式将HashMap转换为字符串,然后传递给Native层。Native层接收到字符串后,再进行反序列化,恢复为HashMap或其他相应的数据结构。

具体步骤如下:

  1. ArkTs端序列化:使用JSON.stringify或其他序列化方法将HashMap转换为字符串。

  2. 传递给Native:通过JNI(Java Native Interface)或其他鸿蒙提供的接口机制,将序列化后的字符串传递给Native层。

  3. Native端反序列化:Native层接收到字符串后,使用相应的解析库(如cJSON、快速JSON等)将字符串反序列化为HashMap对应的数据结构(在C/C++中,可能需要自定义一个类似HashMap的结构,如使用哈希表实现)。

需要注意的是,由于ArkTs和Native的运行环境不同,传递数据时需要确保数据格式和编码的一致性,以避免解析错误。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部