We use essential cookies for the website to function, as well as analytics cookies for analyzing and creating statistics of the website performance. To agree to the use of analytics cookies, click "Accept All". You can manage your preferences at any time by clicking "Cookie Settings" on the footer. More Information.

Only Essential Cookies
Accept All

JSVM-API Development Process

To implement cross-language interaction using JSVM-API, you need to register and load modules based on the JSVM-API mechanism first.

  • ArkTS/JS: Import the .so library and call C++ APIs.

  • Native: Implement module registration via a .cpp file. You need to declare the name of the library to register and define the mappings between the native and JS/ArkTS APIs in the callback registered.

The following demonstrates how to implement cross-language interaction by implementing RunJsVm() in ArkTS/JS code and RunJsVm() in native code.

Creating a Native C++ Project

For details, see Creating an NDK Project.

Implementing Native APIs

By referring to Node-API Development Process, the following code provides a demo for implementing a native method by following "JSVM-API Development Process".

  • In the index.d.ts file, declare the JS methods.

    Collapse
    Word wrap
    Dark theme
    Copy code
    1. // entry/src/main/cpp/types/libentry/index.d.ts
    2. export const runTest: () => void;
  • Associate index.d.ts with .cpp in the oh-package.json5 file.

    Collapse
    Word wrap
    Dark theme
    Copy code
    1. {
    2. "name": "libentry.so",
    3. "types": "./index.d.ts",
    4. "version": "",
    5. "description": "Please describe the basic information."
    6. }
  • Set CMake packaging parameters in the CMakeLists.txt file.

    Collapse
    Word wrap
    Dark theme
    Copy code
    1. # entry/src/main/cpp/CMakeLists.txt
    2. cmake_minimum_required(VERSION 3.4.1)
    3. project(JSVMDemo)
    4. set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
    5. # Set logging information.
    6. add_definitions( "-DLOG_DOMAIN=0xd0d0" )
    7. add_definitions( "-DLOG_TAG=\"testTag\"" )
    8. include_directories(${NATIVERENDER_ROOT_PATH}
    9. ${NATIVERENDER_ROOT_PATH}/include)
    10. # Add a shared library named entry from the source file hello.cpp.
    11. add_library(entry SHARED hello.cpp)
    12. # Link the entry library with the specified shared libraries.
    13. target_link_libraries(entry PUBLIC libace_napi.z.so libjsvm.so libhilog_ndk.z.so)
  • Create entry/src/main/cpp/hello.cpp and implement runTest() on the native side. The code is as follows:

    Collapse
    Word wrap
    Dark theme
    Copy code
    1. // entry/src/main/cpp/hello.cpp
    2. #include "napi/native_api.h"
    3. #include "hilog/log.h"
    4. #include "ark_runtime/jsvm.h"
    5. #define LOG_DOMAIN 0x3200
    6. #define LOG_TAG "APP"
    7. static int g_aa = 0;
    8. #define CHECK_RET(theCall) \
    9. do { \
    10. JSVM_Status cond = theCall; \
    11. if ((cond) != JSVM_OK) { \
    12. const JSVM_ExtendedErrorInfo *info; \
    13. OH_JSVM_GetLastErrorInfo(env, &info); \
    14. OH_LOG_ERROR(LOG_APP, "jsvm fail file: %{public}s line: %{public}d ret = %{public}d message = %{public}s", \
    15. __FILE__, __LINE__, cond, info != nullptr ? info->errorMessage : ""); \
    16. return -1; \
    17. } \
    18. } while (0)
    19. #define CHECK(theCall) \
    20. do { \
    21. JSVM_Status cond = theCall; \
    22. if ((cond) != JSVM_OK) { \
    23. OH_LOG_ERROR(LOG_APP, "jsvm fail file: %{public}s line: %{public}d ret = %{public}d", __FILE__, __LINE__, \
    24. cond); \
    25. return -1; \
    26. } \
    27. } while (0)
    28. // Call theCall and check whether the return value is JSVM_OK.
    29. // If not, call OH_JSVM_GetLastErrorInfo to handle the error and return retVal.
    30. #define JSVM_CALL_BASE(env, theCall, retVal) \
    31. do { \
    32. JSVM_Status cond = theCall; \
    33. if (cond != JSVM_OK) { \
    34. const JSVM_ExtendedErrorInfo *info; \
    35. OH_JSVM_GetLastErrorInfo(env, &info); \
    36. OH_LOG_ERROR(LOG_APP, "jsvm fail file: %{public}s line: %{public}d ret = %{public}d message = %{public}s", \
    37. __FILE__, __LINE__, cond, info != nullptr ? info->errorMessage : ""); \
    38. return retVal; \
    39. } \
    40. } while (0)
    41. // Simplified version of JSVM_CALL_BASE, which returns nullptr.
    42. #define JSVM_CALL(theCall) JSVM_CALL_BASE(env, theCall, nullptr)
    43. // Define OH_JSVM_StrictEquals.
    44. static JSVM_Value IsStrictEquals(JSVM_Env env, JSVM_CallbackInfo info) {
    45. // Obtain the two parameters passed from JS.
    46. size_t argc = 2;
    47. JSVM_Value args[2] = {nullptr};
    48. JSVM_CALL(OH_JSVM_GetCbInfo(env, info, &argc, args, nullptr, nullptr));
    49. // Call OH_JSVM_StrictEquals to check whether two given JS values are strictly equal.
    50. bool result = false;
    51. JSVM_Status status = OH_JSVM_StrictEquals(env, args[0], args[1], &result);
    52. if (status != JSVM_OK) {
    53. OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_StrictEquals: failed");
    54. } else {
    55. OH_LOG_INFO(LOG_APP, "JSVM OH_JSVM_StrictEquals: success: %{public}d", result);
    56. }
    57. JSVM_Value isStrictEqual;
    58. JSVM_CALL(OH_JSVM_GetBoolean(env, result, &isStrictEqual));
    59. return isStrictEqual;
    60. }
    61. // Register the IsStrictEquals callback.
    62. static JSVM_CallbackStruct param[] = {
    63. {.data = nullptr, .callback = IsStrictEquals},
    64. };
    65. static JSVM_CallbackStruct *method = param;
    66. // Set a property descriptor named isStrictEquals and associate it with a callback. This allows the isStrictEquals callback to be called from JS.
    67. static JSVM_PropertyDescriptor descriptor[] = {
    68. {"isStrictEquals", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
    69. };
    70. // Call the C++ code from JS.
    71. const char *srcCallNative = R"JS( let data = '123';
    72. let value = 123;
    73. isStrictEquals(data,value);)JS";
    74. static int32_t TestJSVM() {
    75. JSVM_InitOptions initOptions = {0};
    76. JSVM_VM vm;
    77. JSVM_Env env = nullptr;
    78. JSVM_VMScope vmScope;
    79. JSVM_EnvScope envScope;
    80. JSVM_HandleScope handleScope;
    81. JSVM_Value result;
    82. // Initialize the JSVM instance.
    83. if (g_aa == 0) {
    84. g_aa++;
    85. CHECK(OH_JSVM_Init(&initOptions));
    86. }
    87. // Create a JSVM environment.
    88. CHECK(OH_JSVM_CreateVM(nullptr, &vm));
    89. CHECK(OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env));
    90. CHECK(OH_JSVM_OpenVMScope(vm, &vmScope));
    91. CHECK_RET(OH_JSVM_OpenEnvScope(env, &envScope));
    92. CHECK_RET(OH_JSVM_OpenHandleScope(env, &handleScope));
    93. // Call the test function through the script.
    94. JSVM_Script script;
    95. JSVM_Value jsSrc;
    96. CHECK_RET(OH_JSVM_CreateStringUtf8(env, srcCallNative, JSVM_AUTO_LENGTH, &jsSrc));
    97. CHECK_RET(OH_JSVM_CompileScript(env, jsSrc, nullptr, 0, true, nullptr, &script));
    98. CHECK_RET(OH_JSVM_RunScript(env, script, &result));
    99. // Destroy the JSVM environment.
    100. CHECK_RET(OH_JSVM_CloseHandleScope(env, handleScope));
    101. CHECK_RET(OH_JSVM_CloseEnvScope(env, envScope));
    102. CHECK(OH_JSVM_CloseVMScope(vm, vmScope));
    103. CHECK(OH_JSVM_DestroyEnv(env));
    104. CHECK(OH_JSVM_DestroyVM(vm));
    105. return 0;
    106. }
    107. static napi_value RunTest(napi_env env, napi_callback_info info)
    108. {
    109. TestJSVM();
    110. return nullptr;
    111. }
    112. // Initialize the module.
    113. EXTERN_C_START
    114. static napi_value Init(napi_env env, napi_value exports) {
    115. // Implement the mappings between the ArkTS and C++ APIs.
    116. napi_property_descriptor desc[] = {
    117. {"runTest", nullptr, RunTest, nullptr, nullptr, nullptr, napi_default, nullptr}
    118. };
    119. // Register the native RunJsVm function with the JS exports object, making the native function available to JS.
    120. napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    121. return exports;
    122. }
    123. EXTERN_C_END
    124. static napi_module demoModule = {
    125. .nm_version = 1,
    126. .nm_flags = 0,
    127. .nm_filename = nullptr,
    128. .nm_register_func = Init,
    129. .nm_modname = "entry",
    130. .nm_priv = ((void *)0),
    131. .reserved = {0},
    132. };
    133. extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }

Calling C/C++ APIs in ArkTS

Collapse
Word wrap
Dark theme
Copy code
  1. // Import the native APIs.
  2. import napitest from 'libentry.so';
  3. @Entry
  4. @Component
  5. struct Index {
  6. @State message: string = 'Hello World';
  7. build() {
  8. Row() {
  9. Column() {
  10. Text(this.message)
  11. .fontSize(50)
  12. .fontWeight(FontWeight.Bold)
  13. .onClick(() => {
  14. // runtest
  15. napitest.runTest();
  16. })
  17. }
  18. .width('100%')
  19. }
  20. .height('100%')
  21. }
  22. }

Expected result:

Collapse
Word wrap
Dark theme
Copy code
  1. JSVM OH_JSVM_StrictEquals: success: 0
Search in Guides
Enter a keyword.