1# 使用JSVM-API接口进行函数创建和调用 2<!--Kit: NDK Development--> 3<!--Subsystem: arkcompiler--> 4<!--Owner: @yuanxiaogou; @string_sz--> 5<!--Designer: @knightaoko--> 6<!--Tester: @test_lzz--> 7<!--Adviser: @fang-jinxu--> 8 9## 简介 10 11函数调用允许开发者从JSVM模块中调用JavaScript函数,并传参,或者直接在JSVM模块中创建一个JavaScript函数。 12 13## 基本概念 14 15函数是一种重要的编程概念,用于执行特定任务,提升代码可读性与复用性,简化复杂操作,并实现代码的模块化和结构化,便于理解、维护和扩展。 16 17## 接口说明 18 19| 接口 | 功能说明 | 20|----------------------------|--------------------------------| 21| OH_JSVM_GetCbInfo | 从给定的callback info中获取有关调用的详细信息,如参数和this指针。| 22| OH_JSVM_CallFunction | 在C/C++侧调用JavaScript方法。| 23| OH_JSVM_IsFunction | 判断对象是否为函数对象。 | 24| OH_JSVM_CreateFunction | 用于创建JavaScript函数,用于从JavaScript环境中调用C/C++代码中的函数, 需要设置到一个JavaScript对象中才可以进行调用。 | 25 26## 使用示例 27 28JSVM-API接口开发流程参考[使用JSVM-API实现JS与C/C++语言交互开发流程](use-jsvm-process.md),本文仅对接口对应C++相关代码进行展示。 29 30### OH_JSVM function整合测试 31 32cpp测试全量代码,入口为TEST_FUNC 33``` cpp 34#include "hilog/log.h" 35#include "ark_runtime/jsvm.h" 36 37#define LOG_DOMAIN 0x3200 38#define LOG_TAG "APP" 39 40#define CHECK_RET(cond) \ 41 if ((cond)) { \ 42 const JSVM_ExtendedErrorInfo* info; \ 43 OH_JSVM_GetLastErrorInfo(env, &info); \ 44 OH_LOG_ERROR(LOG_APP, "jsvm fail file: %{public}s line: %{public}d ret = %{public}d message = %{public}s", __FILE__, __LINE__, cond, info != nullptr ? info->errorMessage : ""); \ 45 return -1; \ 46 } 47 48#define CHECK(cond) \ 49 if (!(cond)) { \ 50 OH_LOG_ERROR(LOG_APP, "jsvm fail file: %{public}s line: %{public}d ret = %{public}d", __FILE__, __LINE__, cond); \ 51 return -1; \ 52 } 53 54JSVM_Value NativeCreateFunctionTest(JSVM_Env env, JSVM_CallbackInfo info) { 55 void *data = nullptr; 56 size_t argc = 1; 57 JSVM_Value argv[1] = {nullptr}; 58 JSVM_Value thisArg; 59 // 获取callback 参数信息 60 JSVM_Status ret = OH_JSVM_GetCbInfo(env, info, &argc, &argv[0], &thisArg, &data); 61 if (ret != JSVM_OK) { 62 const JSVM_ExtendedErrorInfo* info; 63 OH_JSVM_GetLastErrorInfo(env, &info); 64 OH_LOG_ERROR(LOG_APP, "jsvm fail file: %{public}s line: %{public}d ret = %{public}d message = %{public}s", __FILE__, __LINE__, ret, info != nullptr ? info->errorMessage : ""); 65 return nullptr; 66 } 67 char message[256]; 68 OH_JSVM_GetValueStringLatin1(env, argv[0], message, 256, nullptr); 69 if (data == nullptr) { 70 OH_LOG_ERROR(LOG_APP, "jsvm: %{public}s; callback data null", message); 71 } else { 72 OH_LOG_INFO(LOG_APP, "jsvm: %{public}s; %{public}s", message, (char*)data); 73 } 74 return nullptr; 75} 76 77static int32_t TEST_FUNC() { 78 JSVM_InitOptions initOptions{}; 79 JSVM_VM vm; 80 JSVM_Env env = nullptr; 81 JSVM_VMScope vmScope; 82 JSVM_EnvScope envScope; 83 JSVM_HandleScope handleScope; 84 JSVM_Value result; 85 static bool isVMInit = false; 86 if (!isVMInit) { 87 isVMInit = true; 88 // 单个进程只用初始化一次 89 OH_JSVM_Init(&initOptions); 90 } 91 CHECK_RET(OH_JSVM_CreateVM(nullptr, &vm)); 92 CHECK_RET(OH_JSVM_CreateEnv(vm, 0, nullptr, &env)); 93 CHECK_RET(OH_JSVM_OpenVMScope(vm, &vmScope)); 94 CHECK_RET(OH_JSVM_OpenEnvScope(env, &envScope)); 95 CHECK_RET(OH_JSVM_OpenHandleScope(env, &handleScope)); 96 97 // 创建并检查函数 98 char hello[] = "Hello World!"; 99 JSVM_CallbackStruct cb = {NativeCreateFunctionTest, (void*)hello}; 100 JSVM_Value func; 101 CHECK_RET(OH_JSVM_CreateFunction(env, "", JSVM_AUTO_LENGTH, &cb, &func)); 102 bool isFunction = false; 103 CHECK_RET(OH_JSVM_IsFunction(env, func, &isFunction)); 104 CHECK(isFunction); 105 106 // 将函数设置到全局对象中 107 JSVM_Value global; 108 CHECK_RET(OH_JSVM_GetGlobal(env, &global)); 109 JSVM_Value key; 110 CHECK_RET(OH_JSVM_CreateStringUtf8(env, "NativeFunc", JSVM_AUTO_LENGTH, &key)); 111 CHECK_RET(OH_JSVM_SetProperty(env, global, key, func)); 112 113 // 通过call 接口调用函数 114 JSVM_Value argv[1] = {nullptr}; 115 OH_JSVM_CreateStringUtf8(env, "jsvm api call function", JSVM_AUTO_LENGTH, &argv[0]); 116 CHECK_RET(OH_JSVM_CallFunction(env, global, func, 1, argv, &result)); 117 118 // 通过script调用函数 119 JSVM_Script script; 120 JSVM_Value jsSrc; 121 const char* srcCallNative = R"JS(NativeFunc('js source call function');)JS"; 122 CHECK_RET(OH_JSVM_CreateStringUtf8(env, srcCallNative, JSVM_AUTO_LENGTH, &jsSrc)); 123 CHECK_RET(OH_JSVM_CompileScript(env, jsSrc, nullptr, 0, true, nullptr, &script)); 124 CHECK_RET(OH_JSVM_RunScript(env, script, &result)); 125 126 CHECK_RET(OH_JSVM_CloseHandleScope(env, handleScope)); 127 CHECK_RET(OH_JSVM_CloseEnvScope(env, envScope)); 128 CHECK_RET(OH_JSVM_CloseVMScope(vm, vmScope)); 129 CHECK_RET(OH_JSVM_DestroyEnv(env)); 130 CHECK_RET(OH_JSVM_DestroyVM(vm)); 131 return 0; 132} 133``` 134<!-- @[jsvm_function_call](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/JSVMAPI/JsvmUsageGuide/UsageInstructionsOne/functioncall/src/main/cpp/hello.cpp) --> 135 136预期的输出 137``` 138jsvm: jsvm api call function; Hello World! 139jsvm: js source call function; Hello World! 140```