harmony 鸿蒙JSVM-API Development Process
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.
// entry/src/main/cpp/types/libentry/index.d.ts
export const runTest: () => void;
- Associate index.d.ts with .cpp in the oh-package.json5 file.
{
"name": "libentry.so",
"types": "./index.d.ts",
"version": "",
"description": "Please describe the basic information."
}
- Set CMake packaging parameters in the CMakeLists.txt file.
# entry/src/main/cpp/CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)
project(JSVMDemo)
set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
# Set logging information.
add_definitions( "-DLOG_DOMAIN=0xd0d0" )
add_definitions( "-DLOG_TAG=\"testTag\"" )
include_directories(${NATIVERENDER_ROOT_PATH}
${NATIVERENDER_ROOT_PATH}/include)
# Add a shared library named entry from the source file hello.cpp.
add_library(entry SHARED hello.cpp)
# Link the entry library with the specified shared libraries.
target_link_libraries(entry PUBLIC libace_napi.z.so libjsvm.so libhilog_ndk.z.so)
- Implement the native runTest function. The code is as follows:
// entry/src/main/cpp/hello.cpp
#include "napi/native_api.h"
#include "hilog/log.h"
#include "ark_runtime/jsvm.h"
#define LOG_DOMAIN 0x3200
#define LOG_TAG "APP"
static int g_aa = 0;
#define CHECK_RET(theCall) \
do { \
JSVM_Status cond = theCall; \
if ((cond) != JSVM_OK) { \
const JSVM_ExtendedErrorInfo *info; \
OH_JSVM_GetLastErrorInfo(env, &info); \
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 : ""); \
return -1; \
} \
} while (0)
#define CHECK(theCall) \
do { \
JSVM_Status cond = theCall; \
if ((cond) != JSVM_OK) { \
OH_LOG_ERROR(LOG_APP, "jsvm fail file: %{public}s line: %{public}d ret = %{public}d", __FILE__, __LINE__, \
cond); \
return -1; \
} \
} while (0)
// Call theCall and check whether the return value is JSVM_OK.
// If not, call OH_JSVM_GetLastErrorInfo to handle the error and return retVal.
#define JSVM_CALL_BASE(env, theCall, retVal) \
do { \
JSVM_Status cond = theCall; \
if (cond != JSVM_OK) { \
const JSVM_ExtendedErrorInfo *info; \
OH_JSVM_GetLastErrorInfo(env, &info); \
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 : ""); \
return retVal; \
} \
} while (0)
// Simplified version of JSVM_CALL_BASE, which returns nullptr.
#define JSVM_CALL(theCall) JSVM_CALL_BASE(env, theCall, nullptr)
// Define OH_JSVM_StrictEquals.
static JSVM_Value IsStrictEquals(JSVM_Env env, JSVM_CallbackInfo info) {
// Obtain the two parameters passed from JS.
size_t argc = 2;
JSVM_Value args[2] = {nullptr};
JSVM_CALL(OH_JSVM_GetCbInfo(env, info, &argc, args, nullptr, nullptr));
// Call OH_JSVM_StrictEquals to check whether two given JS values are strictly equal.
bool result = false;
JSVM_Status status = OH_JSVM_StrictEquals(env, args[0], args[1], &result);
if (status != JSVM_OK) {
OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_StrictEquals: failed");
} else {
OH_LOG_INFO(LOG_APP, "JSVM OH_JSVM_StrictEquals: success: %{public}d", result);
}
JSVM_Value isStrictEqual;
JSVM_CALL(OH_JSVM_GetBoolean(env, result, &isStrictEqual));
return isStrictEqual;
}
// Register the IsStrictEquals callback.
static JSVM_CallbackStruct param[] = {
{.data = nullptr, .callback = IsStrictEquals},
};
static JSVM_CallbackStruct *method = param;
// Set a property descriptor named isStrictEquals and associate it with a callback. This allows the isStrictEquals callback to be called from JS.
static JSVM_PropertyDescriptor descriptor[] = {
{"isStrictEquals", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
};
// Call the C++ code from JS.
const char *srcCallNative = R"JS( let data = '123';
let value = 123;
isStrictEquals(data,value);)JS";
static int32_t TestJSVM() {
JSVM_InitOptions initOptions = {0};
JSVM_VM vm;
JSVM_Env env = nullptr;
JSVM_VMScope vmScope;
JSVM_EnvScope envScope;
JSVM_HandleScope handleScope;
JSVM_Value result;
// Initialize the JSVM instance.
if (g_aa == 0) {
g_aa++;
CHECK(OH_JSVM_Init(&initOptions));
}
// Create a JSVM environment.
CHECK(OH_JSVM_CreateVM(nullptr, &vm));
CHECK(OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env));
CHECK(OH_JSVM_OpenVMScope(vm, &vmScope));
CHECK_RET(OH_JSVM_OpenEnvScope(env, &envScope));
CHECK_RET(OH_JSVM_OpenHandleScope(env, &handleScope));
// Call the test function through the script.
JSVM_Script script;
JSVM_Value jsSrc;
CHECK_RET(OH_JSVM_CreateStringUtf8(env, srcCallNative, JSVM_AUTO_LENGTH, &jsSrc));
CHECK_RET(OH_JSVM_CompileScript(env, jsSrc, nullptr, 0, true, nullptr, &script));
CHECK_RET(OH_JSVM_RunScript(env, script, &result));
// Destroy the JSVM environment.
CHECK_RET(OH_JSVM_CloseHandleScope(env, handleScope));
CHECK_RET(OH_JSVM_CloseEnvScope(env, envScope));
CHECK(OH_JSVM_CloseVMScope(vm, vmScope));
CHECK(OH_JSVM_DestroyEnv(env));
CHECK(OH_JSVM_DestroyVM(vm));
return 0;
}
static napi_value RunTest(napi_env env, napi_callback_info info)
{
TestJSVM();
return nullptr;
}
// Initialize the module.
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
// Implement the mappings between the ArkTS and C++ APIs.
napi_property_descriptor desc[] = {
{"runTest", nullptr, RunTest, nullptr, nullptr, nullptr, napi_default, nullptr}
};
// Register the native RunJsVm function with the JS exports object, making the native function available to JS.
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
return exports;
}
EXTERN_C_END
static napi_module demoModule = {
.nm_version = 1,
.nm_flags = 0,
.nm_filename = nullptr,
.nm_register_func = Init,
.nm_modname = "entry",
.nm_priv = ((void *)0),
.reserved = {0},
};
extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
Calling C/C++ APIs in ArkTS
import hilog from '@ohos.hilog';
// Import the native APIs.
import napitest from 'libentry.so';
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
// runtest
napitest.runTest();
})
}
.width('100%')
}
.height('100%')
}
}
Expected output
JSVM OH_JSVM_StrictEquals: success: 0
你可能感兴趣的鸿蒙文章
harmony 鸿蒙Building an NDK Project with CMake
harmony 鸿蒙Building an NDK Project with the DevEco Studio Template
harmony 鸿蒙NDK Project Building Overview
harmony 鸿蒙Building an NDK Project with Prebuilt Libraries
harmony 鸿蒙C/C++ Library Mechanisms
harmony 鸿蒙Creating an NDK Project
- 所属分类: 后端技术
- 本文标签:
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦