• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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```