1e41f4b71Sopenharmony_ci# Wrapping a Native Object in an ArkTS Object 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci## When to Use 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ciYou 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. 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ci## Example 8e41f4b71Sopenharmony_ci 9e41f4b71Sopenharmony_ci1. Declare the APIs, configure compile settings, and register the modules. 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ci **Declare the APIs.** 12e41f4b71Sopenharmony_ci 13e41f4b71Sopenharmony_ci ```ts 14e41f4b71Sopenharmony_ci // index.d.ts 15e41f4b71Sopenharmony_ci export class MyObject { 16e41f4b71Sopenharmony_ci constructor(arg: number); 17e41f4b71Sopenharmony_ci plusOne: () => number; 18e41f4b71Sopenharmony_ci 19e41f4b71Sopenharmony_ci public get value(); 20e41f4b71Sopenharmony_ci public set value(newVal: number); 21e41f4b71Sopenharmony_ci } 22e41f4b71Sopenharmony_ci ``` 23e41f4b71Sopenharmony_ci 24e41f4b71Sopenharmony_ci **Configure compile settings.** 25e41f4b71Sopenharmony_ci 26e41f4b71Sopenharmony_ci ``` 27e41f4b71Sopenharmony_ci # Minimum version of CMake. 28e41f4b71Sopenharmony_ci cmake_minimum_required(VERSION 3.5.0) 29e41f4b71Sopenharmony_ci project(napi_wrap_demo) 30e41f4b71Sopenharmony_ci 31e41f4b71Sopenharmony_ci set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) 32e41f4b71Sopenharmony_ci 33e41f4b71Sopenharmony_ci if(DEFINED PACKAGE_FIND_FILE) 34e41f4b71Sopenharmony_ci include(${PACKAGE_FIND_FILE}) 35e41f4b71Sopenharmony_ci endif() 36e41f4b71Sopenharmony_ci 37e41f4b71Sopenharmony_ci include_directories(${NATIVERENDER_ROOT_PATH} 38e41f4b71Sopenharmony_ci ${NATIVERENDER_ROOT_PATH}/include) 39e41f4b71Sopenharmony_ci 40e41f4b71Sopenharmony_ci add_definitions("-DLOG_DOMAIN=0x0000") 41e41f4b71Sopenharmony_ci add_definitions("-DLOG_TAG=\"testTag\"") 42e41f4b71Sopenharmony_ci 43e41f4b71Sopenharmony_ci add_library(entry SHARED napi_init.cpp) 44e41f4b71Sopenharmony_ci target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so) 45e41f4b71Sopenharmony_ci ``` 46e41f4b71Sopenharmony_ci 47e41f4b71Sopenharmony_ci **Register modules.** 48e41f4b71Sopenharmony_ci 49e41f4b71Sopenharmony_ci ```cpp 50e41f4b71Sopenharmony_ci // napi_init.cpp 51e41f4b71Sopenharmony_ci #include "napi/native_api.h" 52e41f4b71Sopenharmony_ci #include "hilog/log.h" 53e41f4b71Sopenharmony_ci 54e41f4b71Sopenharmony_ci class MyObject { 55e41f4b71Sopenharmony_ci public: 56e41f4b71Sopenharmony_ci static napi_value Init(napi_env env, napi_value exports); 57e41f4b71Sopenharmony_ci static void Destructor(napi_env env, void* nativeObject, void* finalize_hint); 58e41f4b71Sopenharmony_ci 59e41f4b71Sopenharmony_ci private: 60e41f4b71Sopenharmony_ci explicit MyObject(double value_ = 0); 61e41f4b71Sopenharmony_ci ~MyObject(); 62e41f4b71Sopenharmony_ci 63e41f4b71Sopenharmony_ci static napi_value New(napi_env env, napi_callback_info info); 64e41f4b71Sopenharmony_ci static napi_value GetValue(napi_env env, napi_callback_info info); 65e41f4b71Sopenharmony_ci static napi_value SetValue(napi_env env, napi_callback_info info); 66e41f4b71Sopenharmony_ci static napi_value PlusOne(napi_env env, napi_callback_info info); 67e41f4b71Sopenharmony_ci 68e41f4b71Sopenharmony_ci double value_; 69e41f4b71Sopenharmony_ci napi_env env_; 70e41f4b71Sopenharmony_ci napi_ref wrapper_; 71e41f4b71Sopenharmony_ci }; 72e41f4b71Sopenharmony_ci 73e41f4b71Sopenharmony_ci static thread_local napi_ref g_ref = nullptr; 74e41f4b71Sopenharmony_ci 75e41f4b71Sopenharmony_ci MyObject::MyObject(double value) 76e41f4b71Sopenharmony_ci : value_(value), env_(nullptr), wrapper_(nullptr) {} 77e41f4b71Sopenharmony_ci 78e41f4b71Sopenharmony_ci MyObject::~MyObject() 79e41f4b71Sopenharmony_ci { 80e41f4b71Sopenharmony_ci napi_delete_reference(env_, wrapper_); 81e41f4b71Sopenharmony_ci } 82e41f4b71Sopenharmony_ci 83e41f4b71Sopenharmony_ci void MyObject::Destructor(napi_env env, 84e41f4b71Sopenharmony_ci void* nativeObject, 85e41f4b71Sopenharmony_ci [[maybe_unused]] void* finalize_hint) 86e41f4b71Sopenharmony_ci { 87e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "MyObject::Destructor called"); 88e41f4b71Sopenharmony_ci reinterpret_cast<MyObject*>(nativeObject)->~MyObject(); 89e41f4b71Sopenharmony_ci } 90e41f4b71Sopenharmony_ci 91e41f4b71Sopenharmony_ci napi_value MyObject::Init(napi_env env, napi_value exports) 92e41f4b71Sopenharmony_ci { 93e41f4b71Sopenharmony_ci napi_property_descriptor properties[] = { 94e41f4b71Sopenharmony_ci { "value", 0, 0, GetValue, SetValue, 0, napi_default, 0 }, 95e41f4b71Sopenharmony_ci { "plusOne", nullptr, PlusOne, nullptr, nullptr, nullptr, napi_default, nullptr } 96e41f4b71Sopenharmony_ci }; 97e41f4b71Sopenharmony_ci 98e41f4b71Sopenharmony_ci napi_value cons; 99e41f4b71Sopenharmony_ci napi_define_class(env, "MyObject", NAPI_AUTO_LENGTH, New, nullptr, 2, 100e41f4b71Sopenharmony_ci properties, &cons); 101e41f4b71Sopenharmony_ci 102e41f4b71Sopenharmony_ci napi_create_reference(env, cons, 1, &g_ref); 103e41f4b71Sopenharmony_ci napi_set_named_property(env, exports, "MyObject", cons); 104e41f4b71Sopenharmony_ci return exports; 105e41f4b71Sopenharmony_ci } 106e41f4b71Sopenharmony_ci 107e41f4b71Sopenharmony_ci EXTERN_C_START 108e41f4b71Sopenharmony_ci static napi_value Init(napi_env env, napi_value exports) 109e41f4b71Sopenharmony_ci { 110e41f4b71Sopenharmony_ci MyObject::Init(env, exports); 111e41f4b71Sopenharmony_ci return exports; 112e41f4b71Sopenharmony_ci } 113e41f4b71Sopenharmony_ci EXTERN_C_END 114e41f4b71Sopenharmony_ci 115e41f4b71Sopenharmony_ci static napi_module nativeModule = { 116e41f4b71Sopenharmony_ci .nm_version = 1, 117e41f4b71Sopenharmony_ci .nm_flags = 0, 118e41f4b71Sopenharmony_ci .nm_filename = nullptr, 119e41f4b71Sopenharmony_ci .nm_register_func = Init, 120e41f4b71Sopenharmony_ci .nm_modname = "entry", 121e41f4b71Sopenharmony_ci .nm_priv = nullptr, 122e41f4b71Sopenharmony_ci .reserved = { 0 }, 123e41f4b71Sopenharmony_ci }; 124e41f4b71Sopenharmony_ci 125e41f4b71Sopenharmony_ci extern "C" __attribute__((constructor)) void RegisterObjectWrapModule() 126e41f4b71Sopenharmony_ci { 127e41f4b71Sopenharmony_ci napi_module_register(&nativeModule); 128e41f4b71Sopenharmony_ci } 129e41f4b71Sopenharmony_ci ``` 130e41f4b71Sopenharmony_ci 131e41f4b71Sopenharmony_ci2. Wrap a C++ object in an ArkJS object in a constructor. 132e41f4b71Sopenharmony_ci 133e41f4b71Sopenharmony_ci ```cpp 134e41f4b71Sopenharmony_ci napi_value MyObject::New(napi_env env, napi_callback_info info) 135e41f4b71Sopenharmony_ci { 136e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "MyObject::New called"); 137e41f4b71Sopenharmony_ci 138e41f4b71Sopenharmony_ci napi_value newTarget; 139e41f4b71Sopenharmony_ci napi_get_new_target(env, info, &newTarget); 140e41f4b71Sopenharmony_ci if (newTarget != nullptr) { 141e41f4b71Sopenharmony_ci // Invoked as the constructor `new MyObject(...)`. 142e41f4b71Sopenharmony_ci size_t argc = 1; 143e41f4b71Sopenharmony_ci napi_value args[1]; 144e41f4b71Sopenharmony_ci napi_value jsThis; 145e41f4b71Sopenharmony_ci napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr); 146e41f4b71Sopenharmony_ci 147e41f4b71Sopenharmony_ci double value = 0.0; 148e41f4b71Sopenharmony_ci napi_valuetype valuetype; 149e41f4b71Sopenharmony_ci napi_typeof(env, args[0], &valuetype); 150e41f4b71Sopenharmony_ci if (valuetype != napi_undefined) { 151e41f4b71Sopenharmony_ci napi_get_value_double(env, args[0], &value); 152e41f4b71Sopenharmony_ci } 153e41f4b71Sopenharmony_ci 154e41f4b71Sopenharmony_ci MyObject* obj = new MyObject(value); 155e41f4b71Sopenharmony_ci 156e41f4b71Sopenharmony_ci obj->env_ = env; 157e41f4b71Sopenharmony_ci // Use napi_wrap to wrap the C++ object obj in the ArkTS object jsThis. 158e41f4b71Sopenharmony_ci napi_wrap(env, 159e41f4b71Sopenharmony_ci jsThis, 160e41f4b71Sopenharmony_ci reinterpret_cast<void*>(obj), 161e41f4b71Sopenharmony_ci MyObject::Destructor, 162e41f4b71Sopenharmony_ci nullptr, // finalize_hint 163e41f4b71Sopenharmony_ci &obj->wrapper_); 164e41f4b71Sopenharmony_ci 165e41f4b71Sopenharmony_ci return jsThis; 166e41f4b71Sopenharmony_ci } else { 167e41f4b71Sopenharmony_ci // Invoked as the plain function `MyObject(...)`. 168e41f4b71Sopenharmony_ci size_t argc = 1; 169e41f4b71Sopenharmony_ci napi_value args[1]; 170e41f4b71Sopenharmony_ci napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 171e41f4b71Sopenharmony_ci 172e41f4b71Sopenharmony_ci napi_value cons; 173e41f4b71Sopenharmony_ci napi_get_reference_value(env, g_ref, &cons); 174e41f4b71Sopenharmony_ci napi_value instance; 175e41f4b71Sopenharmony_ci napi_new_instance(env, cons, argc, args, &instance); 176e41f4b71Sopenharmony_ci 177e41f4b71Sopenharmony_ci return instance; 178e41f4b71Sopenharmony_ci } 179e41f4b71Sopenharmony_ci } 180e41f4b71Sopenharmony_ci ``` 181e41f4b71Sopenharmony_ci 182e41f4b71Sopenharmony_ci3. Retrieve the C++ object from the ArkTS object and perform subsequent operations on the C++ object. 183e41f4b71Sopenharmony_ci 184e41f4b71Sopenharmony_ci ```cpp 185e41f4b71Sopenharmony_ci napi_value MyObject::GetValue(napi_env env, napi_callback_info info) 186e41f4b71Sopenharmony_ci { 187e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "MyObject::GetValue called"); 188e41f4b71Sopenharmony_ci 189e41f4b71Sopenharmony_ci napi_value jsThis; 190e41f4b71Sopenharmony_ci napi_get_cb_info(env, info, nullptr, nullptr, &jsThis, nullptr); 191e41f4b71Sopenharmony_ci 192e41f4b71Sopenharmony_ci MyObject* obj; 193e41f4b71Sopenharmony_ci // Use napi_unwrap to retrieve obj (the C++ object) previously wrapped in jsThis (the ArkTS object), and perform subsequent operations. 194e41f4b71Sopenharmony_ci napi_unwrap(env, jsThis, reinterpret_cast<void**>(&obj)); 195e41f4b71Sopenharmony_ci napi_value num; 196e41f4b71Sopenharmony_ci napi_create_double(env, obj->value_, &num); 197e41f4b71Sopenharmony_ci 198e41f4b71Sopenharmony_ci return num; 199e41f4b71Sopenharmony_ci } 200e41f4b71Sopenharmony_ci 201e41f4b71Sopenharmony_ci napi_value MyObject::SetValue(napi_env env, napi_callback_info info) 202e41f4b71Sopenharmony_ci { 203e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "MyObject::SetValue called"); 204e41f4b71Sopenharmony_ci 205e41f4b71Sopenharmony_ci size_t argc = 1; 206e41f4b71Sopenharmony_ci napi_value value; 207e41f4b71Sopenharmony_ci napi_value jsThis; 208e41f4b71Sopenharmony_ci 209e41f4b71Sopenharmony_ci napi_get_cb_info(env, info, &argc, &value, &jsThis, nullptr); 210e41f4b71Sopenharmony_ci 211e41f4b71Sopenharmony_ci MyObject* obj; 212e41f4b71Sopenharmony_ci // Use napi_unwrap to retrieve obj (the C++ object) previously wrapped in jsThis (the ArkTS object), and perform subsequent operations. 213e41f4b71Sopenharmony_ci napi_unwrap(env, jsThis, reinterpret_cast<void**>(&obj)); 214e41f4b71Sopenharmony_ci napi_get_value_double(env, value, &obj->value_); 215e41f4b71Sopenharmony_ci 216e41f4b71Sopenharmony_ci return nullptr; 217e41f4b71Sopenharmony_ci } 218e41f4b71Sopenharmony_ci 219e41f4b71Sopenharmony_ci napi_value MyObject::PlusOne(napi_env env, napi_callback_info info) 220e41f4b71Sopenharmony_ci { 221e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "MyObject::PlusOne called"); 222e41f4b71Sopenharmony_ci 223e41f4b71Sopenharmony_ci napi_value jsThis; 224e41f4b71Sopenharmony_ci napi_get_cb_info(env, info, nullptr, nullptr, &jsThis, nullptr); 225e41f4b71Sopenharmony_ci 226e41f4b71Sopenharmony_ci MyObject* obj; 227e41f4b71Sopenharmony_ci // Use napi_unwrap to retrieve obj (the C++ object) previously wrapped in jsThis (the ArkTS object), and perform subsequent operations. 228e41f4b71Sopenharmony_ci napi_unwrap(env, jsThis, reinterpret_cast<void**>(&obj)); 229e41f4b71Sopenharmony_ci obj->value_ += 1; 230e41f4b71Sopenharmony_ci napi_value num; 231e41f4b71Sopenharmony_ci napi_create_double(env, obj->value_, &num); 232e41f4b71Sopenharmony_ci 233e41f4b71Sopenharmony_ci return num; 234e41f4b71Sopenharmony_ci } 235e41f4b71Sopenharmony_ci ``` 236e41f4b71Sopenharmony_ci 237e41f4b71Sopenharmony_ci4. The following provides the sample ArkTS code. 238e41f4b71Sopenharmony_ci 239e41f4b71Sopenharmony_ci ```ts 240e41f4b71Sopenharmony_ci import hilog from '@ohos.hilog'; 241e41f4b71Sopenharmony_ci import { MyObject } from 'libentry.so'; 242e41f4b71Sopenharmony_ci 243e41f4b71Sopenharmony_ci let object : MyObject = new MyObject(0); 244e41f4b71Sopenharmony_ci object.value = 1023; 245e41f4b71Sopenharmony_ci hilog.info(0x0000, 'testTag', 'MyObject value after set: %{public}d', object.value); 246e41f4b71Sopenharmony_ci hilog.info(0x0000, 'testTag', 'MyObject plusOne: %{public}d', object.plusOne()); 247e41f4b71Sopenharmony_ci ``` 248