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