HarmonyOS NDK接口jsvm是否可以在同一个应用中启动多个

初始化代码如下,发现这样初始化jsvm后全局只能初始化一遍,去掉去重的代码就是VM_INIT判断后运行,尝试多次初始化进程似乎会陷入无限循环中,直接卡死。

if (!VM_INIT) {
    // JSVM only need init once
    JSVM_InitOptions initOptions;
    memset(&initOptions, 0, sizeof(initOptions));
    // initOptions.externalReferences = externals;
    OH_JSVM_Init(&initOptions);
    PrintVmInfo();
    VM_INIT = true;
}
// 创建虚拟机实例
OH_JSVM_CreateVM(nullptr, &vm);
OH_JSVM_OpenVMScope(vm, &vmScope);
// 创建js运行环境上下文
JSVM_PropertyDescriptor descriptor[] = {
    {"setTimeout", NULL, &set_timeout_cb, NULL, NULL, NULL, JSVM_DEFAULT},
    {"clearTimeout", NULL, &clear_timeout_cb, NULL, NULL, NULL, JSVM_DEFAULT},
    {"setInterval", NULL, &set_interval_cb, NULL, NULL, NULL, JSVM_DEFAULT},
    {"clearInterval", NULL, &clear_interval_cb, NULL, NULL, NULL, JSVM_DEFAULT},
};
OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &jsvm_env);
return jsvm_env;

是否jsvm在设计上一个应用只能启动一个jscore环境,如果想要能同时存在多个该如何做?

HarmonyOS
20h前
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
shlp

使用JSVM-API接口创建多个引擎执行JS代码并销毁参考下:

1、提供创建JSVM运行环境的对外接口并返回对应唯一ID。

static napi_value CreateJsCore(napi_env env1, napi_callback_info info) {
    OH_LOG_INFO(LOG_APP, "JSVM CreateJsCore START");
    size_t argc = 1;
    napi_value argv[1];
    napi_get_cb_info(env1, info, &argc, argv, nullptr, nullptr);
    if (argc < 1) {
        OH_LOG_ERROR(LOG_APP, "JSVM CreateJsCore the number of params must be one");
        return nullptr;
    }
    g_napiEnvMap[ENVTAG_NUMBER] = env1;
    g_taskQueueMap[ENVTAG_NUMBER] = deque<Task *>{};
    // 将TS侧传入的回调函数与env对应存储方便后续调用
    napi_ref callFun;
    napi_create_reference(env1, argv[0], 1, &callFun);
    g_callBackMap[ENVTAG_NUMBER] = callFun;
    napi_value coreID = 0;
    {
        std::lock_guard<std::mutex> lock_guard(envMapLock);
        CreateArkJSContext();
        napi_create_uint32(env1, ENVTAG_NUMBER, &coreID);
        ENVTAG_NUMBER++;
    }
    OH_LOG_INFO(LOG_APP, "JSVM CreateJsCore END");
    return coreID;
}

2、对外提供执行JS代码接口,通过coreID在对应的JSVN环境中执行JS代码。

static napi_value EvalUateJS(napi_env env, napi_callback_info info) {
    OH_LOG_INFO(LOG_APP, "JSVM EvalUateJS START");
    size_t argc = 2;
    napi_value args[2] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    uint32_t envId;
    napi_status status = napi_get_value_uint32(env, args[0], &envId);
    if (status != napi_ok) {
        OH_LOG_ERROR(LOG_APP, "EvalUateJS first param should be number");
        return nullptr;
    }
    if (g_envMap.count(envId) == 0 || g_envMap[envId] == nullptr) {
        OH_LOG_ERROR(LOG_APP, "EvalUateJS env is null");
        return nullptr;
    }
    std::string dataStr = napiValueToString(env, args[1]);
    napi_value res = nullptr;
    std::lock_guard<std::mutex> lock_guard(mutexLock);
    {
        // open handle scope
        JSVM_HandleScope handlescope;
        OH_JSVM_OpenHandleScope(*g_envMap[envId], &handlescope);
        // compile js script
        JSVM_Value sourcecodevalue;
        OH_JSVM_CreateStringUtf8(*g_envMap[envId], dataStr.c_str(), dataStr.size(), &sourcecodevalue);
        JSVM_Script script;
        OH_JSVM_CompileScript(*g_envMap[envId], sourcecodevalue, nullptr, 0, true, nullptr, &script);
        // run js script
        JSVM_Value result;
        OH_JSVM_RunScript(*g_envMap[envId], script, &result);
        JSVM_ValueType type;
        OH_JSVM_Typeof(*g_envMap[envId], result, &type);
        OH_LOG_INFO(LOG_APP, "JSVM API TEST type: %{public}d", type);
        // Execute tasks in the current env event queue
        while (!g_taskQueueMap[envId].empty()) {
            auto task = g_taskQueueMap[envId].front();
            g_taskQueueMap[envId].pop_front();
            task->Run();
            delete task;
        }
        if (type == JSVM_STRING) {
            std::string stdResult = fromOHStringValue(*g_envMap[envId], result);
            napi_create_string_utf8(env, stdResult.c_str(), stdResult.length(), &res);
        } else if (type == JSVM_BOOLEAN) {
            bool ret = false;
            std::string stdResult;
            OH_JSVM_GetValueBool(*g_envMap[envId], result, &ret);
            ret ? stdResult = "true" : stdResult = "false";
            napi_create_string_utf8(env, stdResult.c_str(), stdResult.length(), &res);
        } else if (type == JSVM_NUMBER) {
            int32_t num;
            OH_JSVM_GetValueInt32(*g_envMap[envId], result, &num);
            std::string stdResult = std::to_string(num);
            napi_create_string_utf8(env, stdResult.c_str(), stdResult.length(), &res);
        } else if (type == JSVM_OBJECT) {
            JSVM_Value objResult;
            OH_JSVM_JsonStringify(*g_envMap[envId], result, &objResult);
            std::string stdResult = fromOHStringValue(*g_envMap[envId], objResult);
            napi_create_string_utf8(env, stdResult.c_str(), stdResult.length(), &res);
        }
        OH_JSVM_CloseHandleScope(*g_envMap[envId], handlescope);
    }
    OH_LOG_INFO(LOG_APP, "JSVM EvalUateJS END");
    return res;
}

3、对外提供释放JSVM环境接口,通过envId释放对应环境。

static napi_value ReleaseJsCore(napi_env env1, napi_callback_info info) {
    OH_LOG_INFO(LOG_APP, "JSVM ReleaseJsCore START");
    size_t argc = 1;
    napi_value argv[1];
    napi_get_cb_info(env1, info, &argc, argv, nullptr, nullptr);
    if (argc < 1) {
        OH_LOG_ERROR(LOG_APP, "JSVM ReleaseJsCore the number of params must be one");
        return nullptr;
    }
    uint32_t coreEnvId;
    napi_status status = napi_get_value_uint32(env1, argv[0], &coreEnvId);
    if (status != napi_ok) {
        OH_LOG_ERROR(LOG_APP, "JSVM CreateJsCore napi_get_value_uint32 faild");
        return nullptr;
    }
    if (g_envMap.count(coreEnvId) == 0) {
        OH_LOG_ERROR(LOG_APP, "JSVM CreateJsCore not has env ");
        return nullptr;
    }
    if (g_envMap[coreEnvId] != nullptr) {
        std::lock_guard<std::mutex> lock_guard(envMapLock);
        OH_JSVM_CloseEnvScope(*g_envMap[coreEnvId], g_envScopeMap[coreEnvId]);
        g_envScopeMap.erase(coreEnvId);
        OH_JSVM_DestroyEnv(*g_envMap[coreEnvId]);
        g_envMap[coreEnvId] = nullptr;
        g_envMap.erase(coreEnvId);
        OH_JSVM_CloseVMScope(*g_vmMap[coreEnvId], g_vmScopeMap[coreEnvId]);
        g_vmScopeMap.erase(coreEnvId);
        OH_JSVM_DestroyVM(*g_vmMap[coreEnvId]);
        g_vmMap[coreEnvId] = nullptr;
        g_vmMap.erase(coreEnvId);
        delete[] g_callBackStructMap[coreEnvId];
        g_callBackStructMap[coreEnvId] = nullptr;
        g_callBackStructMap.erase(coreEnvId);
        napi_delete_reference(env1, g_callBackMap[coreEnvId]);
        g_callBackMap.erase(coreEnvId);
        g_taskQueueMap.erase(coreEnvId);
    }
    OH_LOG_INFO(LOG_APP, "JSVM ReleaseJsCore END");
    return nullptr;
}

示例参考链接:https://gitee.com/harmonyos_samples/ExecutingJSWithJSVM

分享
微博
QQ
微信
回复
19h前
相关问题
HarmonyOS 多module同时依赖同一个har
938浏览 • 1回复 待解决
同一个HSP,router.pushUrl的url问题
506浏览 • 1回复 待解决