往期鸿蒙全套实战文章必看:(文中附带全栈鸿蒙学习资料)
- 鸿蒙开发核心知识点,看这篇文章就够了
- 最新版!鸿蒙HarmonyOS Next应用开发实战学习门路
- 鸿蒙HarmonyOS NEXT开发技能最全学习门路指南
- 鸿蒙应用开发实战项目,看这一篇文章就够了(部门项目附源码)
简介
JSVM-API WebAssembly 接口提供了 wasm 字节码编译、wasm 函数优化、wasm cache 序列化和反序列化的能力。
基本概念
- wasm module:表示一个 WebAssembly 模块,通过 OH_JSVM_CompileWasmModule 接口可以从 wasm 字节码或 wasm cache 创建 wasm module。通过 OH_JSVM_IsWasmModuleObject 接口可以判定一个 JSVM_Value 是否是一个 wasm module。
- wasm function:表示 wasm module 中界说的函数,wasm function 在导出后被外部代码利用。OH_JSVM_CompileWasmFunction 接口提供了将 wasm function 编译为优化后的机器码的能力,方便开发者对指定 wasm function 提前编译和函数粒度的并行编译。
- wasm cache:对 wasm module 中的机器码进行序列化,天生的数据被称为 wasm cache。wasm cache 的创建和释放接口分别为 OH_JSVM_CreateWasmCache 和 OH_JSVM_ReleaseCache (对应的 cacheType 为 JSVM_CACHE_TYPE_WASM)。
接口说明
接口功能说明OH_JSVM_CompileWasmModule将 wasm 字节码同步编译为 wasm module。假如提供了 cache 参数,先实验将 cache 反序列为 wasm module,反序列化失败时再执行编译。OH_JSVM_CompileWasmFunction将 wasm module 中指定编号的函数编译为优化后的机器码,现在只使能了最高的优化等级,函数编号的合法性由接口调用者保证。OH_JSVM_IsWasmModuleObject判定传入的值是否是一个 wasm module。OH_JSVM_CreateWasmCache将 wasm module 中的机器码序列化为 wasm cache,假如 wasm module 不包含机器码,则会序列化失败。OH_JSVM_ReleaseCache释放由 JSVM 接口天生的 cache。传入的 cacheType 和 cacheData 必须匹配,否则会产生未界说行为。 利用示例
本文仅对接口对应 C++ 及 ArkTS 相干代码进行展示。
cpp 部门代码:
- // hello.cpp
- #include "napi/native_api.h"
- #include "ark_runtime/jsvm.h"
- #include <hilog/log.h>
- #ifndef CHECK
- #define CHECK(cond) \
- do { \
- if (!(cond)) { \
- OH_LOG_ERROR(LOG_APP, "CHECK FAILED"); \
- abort(); \
- } \
- } while (0)
- #endif
- // 判断一个 JSVM_Value 是否是 wasm module
- static bool IsWasmModuleObject(JSVM_Env env, JSVM_Value value) {
- bool result;
- JSVM_Status status = OH_JSVM_IsWasmModuleObject(env, value, &result);
- CHECK(status == JSVM_OK);
- return result;
- }
- // 由 C 字符串创建 JSVM string
- static JSVM_Value CreateString(JSVM_Env env, const char *str) {
- JSVM_Value jsvmStr;
- JSVM_Status status = OH_JSVM_CreateStringUtf8(env, str, JSVM_AUTO_LENGTH, &jsvmStr);
- CHECK(status == JSVM_OK);
- return jsvmStr;
- }
- // 由 C int32_t 创建 JSVM number
- static JSVM_Value CreateInt32(JSVM_Env env, int32_t val) {
- JSVM_Value jsvmInt32;
- JSVM_Status status = OH_JSVM_CreateInt32(env, val, &jsvmInt32);
- CHECK(status == JSVM_OK);
- return jsvmInt32;
- }
- // 对 wasm module 进行实例化
- static JSVM_Value InstantiateWasmModule(JSVM_Env env, JSVM_Value wasmModule) {
- JSVM_Status status = JSVM_OK;
- JSVM_Value globalThis;
- status = OH_JSVM_GetGlobal(env, &globalThis);
- CHECK(status == JSVM_OK);
- JSVM_Value WebAssembly;
- status = OH_JSVM_GetProperty(env, globalThis, CreateString(env, "WebAssembly"), &WebAssembly);
- CHECK(status == JSVM_OK);
- JSVM_Value WebAssemblyInstance;
- status = OH_JSVM_GetProperty(env, WebAssembly, CreateString(env, "Instance"), &WebAssemblyInstance);
- CHECK(status == JSVM_OK);
- JSVM_Value instance;
- JSVM_Value argv[] = {wasmModule};
- status = OH_JSVM_NewInstance(env, WebAssemblyInstance, 1, argv, &instance);
- CHECK(status == JSVM_OK);
- return instance;
- }
- // 获取 wasm 字节码 (add 模块)
- static std::vector<uint8_t> GetAddWasmBuffer() {
- // 以下 wasmBuffer 对应的 wasm 字节码文本格式如下所示,只包含了一个函数 add
- // (module
- // (func $add (param $lhs i32) (param $rhs i32) (result i32)
- // local.get $lhs
- // local.get $rhs
- // i32.add
- // )
- // (export "add" (func $add))
- // )
- std::vector<uint8_t> wasmBuffer = {0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01,
- 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07,
- 0x07, 0x01, 0x03, 0x61, 0x64, 0x64, 0x00, 0x00, 0x0a, 0x09, 0x01,
- 0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b};
- return wasmBuffer;
- }
- // 验证 wasm instance 功能 (add 模块)
- static void VerifyAddWasmInstance(JSVM_Env env, JSVM_Value wasmInstance) {
- JSVM_Status status = JSVM_OK;
- // 从 wasm instance 获取 exports.add 函数
- JSVM_Value exports;
- status = OH_JSVM_GetProperty(env, wasmInstance, CreateString(env, "exports"), &exports);
- CHECK(status == JSVM_OK);
- JSVM_Value add;
- status = OH_JSVM_GetProperty(env, exports, CreateString(env, "add"), &add);
- CHECK(status == JSVM_OK);
- // 执行 exports.add(1, 2),期望得到结果 3
- JSVM_Value undefined;
- OH_JSVM_GetUndefined(env, &undefined);
- JSVM_Value one = CreateInt32(env, 1);
- JSVM_Value two = CreateInt32(env, 2);
- JSVM_Value argv[] = {one, two};
- JSVM_Value result;
- status = OH_JSVM_CallFunction(env, undefined, add, 2, argv, &result);
- CHECK(status == JSVM_OK);
- int32_t resultInt32;
- OH_JSVM_GetValueInt32(env, result, &resultInt32);
- CHECK(resultInt32 == 3);
- }
- // WebAssembly demo 主函数
- static JSVM_Value WasmDemo(JSVM_Env env, JSVM_CallbackInfo info) {
- JSVM_Status status = JSVM_OK;
- std::vector<uint8_t> wasmBuffer = GetAddWasmBuffer();
- uint8_t *wasmBytecode = wasmBuffer.data();
- size_t wasmBytecodeLength = wasmBuffer.size();
- JSVM_Value wasmModule;
- // 根据 wasm 字节码得到 wasm module
- status = OH_JSVM_CompileWasmModule(env, wasmBytecode, wasmBytecodeLength, NULL, 0, NULL, &wasmModule);
- CHECK(status == JSVM_OK);
- CHECK(IsWasmModuleObject(env, wasmModule));
- // 对当前 wasm module 中定义的第一个函数 (即 add) 执行编译优化
- int32_t functionIndex = 0;
- // 注意:当前只支持 high level optimization,即传入 JSVM_WASM_OPT_BASELINE 和传入 JSVM_WASM_OPT_HIGH 效果是一样的
- status = OH_JSVM_CompileWasmFunction(env, wasmModule, functionIndex, JSVM_WASM_OPT_HIGH);
- CHECK(status == JSVM_OK);
- // 对编译得到的 wasm module 进行实例化
- JSVM_Value wasmInstance = InstantiateWasmModule(env, wasmModule);
- // 对实例化的 wasm instance 中的函数进行功能验证
- VerifyAddWasmInstance(env, wasmInstance);
- // 创建 wasm cache
- const uint8_t *wasmCacheData = NULL;
- size_t wasmCacheLength = 0;
- status = OH_JSVM_CreateWasmCache(env, wasmModule, &wasmCacheData, &wasmCacheLength);
- CHECK(status == JSVM_OK);
- // 期望 wasm cache 创建成功
- CHECK(wasmCacheData != NULL);
- CHECK(wasmCacheLength > 0);
- // 通过将 wasm cache 赋值来模拟 cache 持久化,实际使用场景可能将 wasm cache 保存到文件
- std::vector<uint8_t> cacheBuffer(wasmCacheData, wasmCacheData + wasmCacheLength);
- // cache 一旦保存完成后,需要显式释放,以免发生内存泄露
- // 注意:传入的 JSVM_CacheType 必须匹配
- status = OH_JSVM_ReleaseCache(env, wasmCacheData, JSVM_CACHE_TYPE_WASM);
- CHECK(status == JSVM_OK);
- // 使用 wasm code 反序列化来生成 wasm module
- bool cacheRejected;
- JSVM_Value wasmModule2;
- status = OH_JSVM_CompileWasmModule(env, wasmBytecode, wasmBytecodeLength, cacheBuffer.data(), cacheBuffer.size(),
- &cacheRejected, &wasmModule2);
- CHECK(status == JSVM_OK);
- // 传入的 wasm cache 如果是匹配的,且内部校验通过 (如版本),则会接受 cache
- CHECK(cacheRejected == false);
- CHECK(IsWasmModuleObject(env, wasmModule2));
- // 对反序列化得到的 wasmModule2 进行同样的操作:函数编译、实例化、验证功能,期望也都是通过的
- status = OH_JSVM_CompileWasmFunction(env, wasmModule2, functionIndex, JSVM_WASM_OPT_HIGH);
- CHECK(status == JSVM_OK);
- JSVM_Value wasmInstance2 = InstantiateWasmModule(env, wasmModule);
- VerifyAddWasmInstance(env, wasmInstance2);
- JSVM_Value result;
- OH_JSVM_GetBoolean(env, true, &result);
- return result;
- }
- // WasmDemo 方法注册回调
- static JSVM_CallbackStruct param[] = {
- {.data = nullptr, .callback = WasmDemo}
- };
- static JSVM_CallbackStruct *method = param;
- // 将 C++ callback WasmDemo 函数注册为 JSVM globalThis.wasmDemo 属性,供 JS 侧调用
- static JSVM_PropertyDescriptor descriptor[] = {
- {"wasmDemo", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
- };
复制代码 ArkTS 侧示例代码:
- import hilog from "@ohos.hilog"
- // 通过 import 的方式,引入 Native 能力。
- import napitest from "libentry.so"
- try {
- let result = napitest.runJsVm('wasmDemo()');
- hilog.info(0x0000, 'JSVM', 'WasmDemo result: %{public}s', result);
- } catch (error) {
- hilog.error(0x0000, 'JSVM', 'WasmDemo result: %{public}s', error.message);
- }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |