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