harmony 鸿蒙Wrapping a Native Object in an ArkTS Object
Wrapping a Native Object in an ArkTS Object
When to Use
You can use napi_wrap to wrap a C++ object in an ArkTS object, and use napi_unwrap to retrieve the C++ object previously wrapped in the ArkTS object for subsequent operations.
Example
- Declare the APIs, configure compile settings, and register the modules.
Declare the APIs.
// index.d.ts
export class MyObject {
constructor(arg: number);
plusOne: () => number;
public get value();
public set value(newVal: number);
}
Configure compile settings.
# Minimum version of CMake.
cmake_minimum_required(VERSION 3.5.0)
project(napi_wrap_demo)
set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
if(DEFINED PACKAGE_FIND_FILE)
include(${PACKAGE_FIND_FILE})
endif()
include_directories(${NATIVERENDER_ROOT_PATH}
${NATIVERENDER_ROOT_PATH}/include)
add_definitions("-DLOG_DOMAIN=0x0000")
add_definitions("-DLOG_TAG=\"testTag\"")
add_library(entry SHARED napi_init.cpp)
target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so)
Register modules.
// napi_init.cpp
#include "napi/native_api.h"
#include "hilog/log.h"
class MyObject {
public:
static napi_value Init(napi_env env, napi_value exports);
static void Destructor(napi_env env, void* nativeObject, void* finalize_hint);
private:
explicit MyObject(double value_ = 0);
~MyObject();
static napi_value New(napi_env env, napi_callback_info info);
static napi_value GetValue(napi_env env, napi_callback_info info);
static napi_value SetValue(napi_env env, napi_callback_info info);
static napi_value PlusOne(napi_env env, napi_callback_info info);
double value_;
napi_env env_;
napi_ref wrapper_;
};
static thread_local napi_ref g_ref = nullptr;
MyObject::MyObject(double value)
: value_(value), env_(nullptr), wrapper_(nullptr) {}
MyObject::~MyObject()
{
napi_delete_reference(env_, wrapper_);
}
void MyObject::Destructor(napi_env env,
void* nativeObject,
[[maybe_unused]] void* finalize_hint)
{
OH_LOG_INFO(LOG_APP, "MyObject::Destructor called");
delete reinterpret_cast<MyObject*>(nativeObject);
}
napi_value MyObject::Init(napi_env env, napi_value exports)
{
napi_property_descriptor properties[] = {
{ "value", 0, 0, GetValue, SetValue, 0, napi_default, 0 },
{ "plusOne", nullptr, PlusOne, nullptr, nullptr, nullptr, napi_default, nullptr }
};
napi_value cons;
napi_define_class(env, "MyObject", NAPI_AUTO_LENGTH, New, nullptr, 2,
properties, &cons);
napi_create_reference(env, cons, 1, &g_ref);
napi_set_named_property(env, exports, "MyObject", cons);
return exports;
}
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports)
{
MyObject::Init(env, exports);
return exports;
}
EXTERN_C_END
static napi_module nativeModule = {
.nm_version = 1,
.nm_flags = 0,
.nm_filename = nullptr,
.nm_register_func = Init,
.nm_modname = "entry",
.nm_priv = nullptr,
.reserved = { 0 },
};
extern "C" __attribute__((constructor)) void RegisterObjectWrapModule()
{
napi_module_register(&nativeModule);
}
- Wrap a C++ object in an ArkTS object in a constructor.
napi_value MyObject::New(napi_env env, napi_callback_info info)
{
OH_LOG_INFO(LOG_APP, "MyObject::New called");
napi_value newTarget;
napi_get_new_target(env, info, &newTarget);
if (newTarget != nullptr) {
// Invoked as the constructor `new MyObject(...)`.
size_t argc = 1;
napi_value args[1];
napi_value jsThis;
napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
double value = 0.0;
napi_valuetype valuetype;
napi_typeof(env, args[0], &valuetype);
if (valuetype != napi_undefined) {
napi_get_value_double(env, args[0], &value);
}
MyObject* obj = new MyObject(value);
obj->env_ = env;
// Use napi_wrap to wrap the C++ object obj in the ArkTS object jsThis.
napi_status status = napi_wrap(env,
jsThis,
reinterpret_cast<void*>(obj),
MyObject::Destructor,
nullptr, // finalize_hint
&obj->wrapper_);
// If napi_wrap fails, the allocated memory must be manually released to prevent memory leaks.
if (status != napi_ok) {
OH_LOG_INFO(LOG_APP, "Failed to bind native object to js object"
", return code: %{public}d", status);
delete obj;
return jsThis;
}
// Obtain the napi_ref behavior from result of napi_wrap() to create a strong reference to jsThis.
// If you do not want to manage the lifecycle of jsThis, pass nullptr in the last parameter of napi_wrap
// or call napi_reference_unref to convert napi_ref to a weak reference.
uint32_t refCount = 0;
napi_reference_unref(env, obj->wrapper_, &refCount);
return jsThis;
} else {
// Invoked as the plain function `MyObject(...)`.
size_t argc = 1;
napi_value args[1];
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
napi_value cons;
napi_get_reference_value(env, g_ref, &cons);
napi_value instance;
napi_new_instance(env, cons, argc, args, &instance);
return instance;
}
}
- Retrieve the C++ object from the ArkTS object and perform subsequent operations on the C++ object.
napi_value MyObject::GetValue(napi_env env, napi_callback_info info)
{
OH_LOG_INFO(LOG_APP, "MyObject::GetValue called");
napi_value jsThis;
napi_get_cb_info(env, info, nullptr, nullptr, &jsThis, nullptr);
MyObject* obj;
// Use napi_unwrap to retrieve obj (the C++ object) previously wrapped in jsThis (the ArkTS object), and perform subsequent operations.
napi_unwrap(env, jsThis, reinterpret_cast<void**>(&obj));
napi_value num;
napi_create_double(env, obj->value_, &num);
return num;
}
napi_value MyObject::SetValue(napi_env env, napi_callback_info info)
{
OH_LOG_INFO(LOG_APP, "MyObject::SetValue called");
size_t argc = 1;
napi_value value;
napi_value jsThis;
napi_get_cb_info(env, info, &argc, &value, &jsThis, nullptr);
MyObject* obj;
// Use napi_unwrap to retrieve obj (the C++ object) previously wrapped in jsThis (the ArkTS object), and perform subsequent operations.
napi_unwrap(env, jsThis, reinterpret_cast<void**>(&obj));
napi_get_value_double(env, value, &obj->value_);
return nullptr;
}
napi_value MyObject::PlusOne(napi_env env, napi_callback_info info)
{
OH_LOG_INFO(LOG_APP, "MyObject::PlusOne called");
napi_value jsThis;
napi_get_cb_info(env, info, nullptr, nullptr, &jsThis, nullptr);
MyObject* obj;
// Use napi_unwrap to retrieve obj (the C++ object) previously wrapped in jsThis (the ArkTS object), and perform subsequent operations.
napi_unwrap(env, jsThis, reinterpret_cast<void**>(&obj));
obj->value_ += 1;
napi_value num;
napi_create_double(env, obj->value_, &num);
return num;
}
- The following provides the sample ArkTS code.
import hilog from '@ohos.hilog';
import { MyObject } from 'libentry.so';
let object : MyObject = new MyObject(0);
object.value = 1023;
hilog.info(0x0000, 'testTag', 'MyObject value after set: %{public}d', object.value);
hilog.info(0x0000, 'testTag', 'MyObject plusOne: %{public}d', object.plusOne());
你可能感兴趣的鸿蒙文章
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
0
赞
- 所属分类: 后端技术
- 本文标签:
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦