1# Working with Classes Using Node-API
2
3## Introduction
4
5Node-API provides APIs for managing ArkTS classes, for example, defining an ArkTS class and creating an ArkTS instance, in C/C++.
6
7## Basic Concepts
8
9To begin with, it is important to understand the following basic concepts:
10
11- Class: a template used to create an object. It provides a way to define object properties and methods in a structured manner. Classes in ArkTS are based on prototypes and added with unique syntax and semantics.
12- Instance: an object created from a class. A class defines the structure and behavior of an object, and an instance is a specific representation of a class. Instantiating a class allows access to the properties and methods defined in the class. Each instance has its own property values.
13
14## Available APIs
15
16The following table lists the APIs for manipulating ArkTS classes.
17| API| Description|
18| -------- | -------- |
19| napi_new_instance | Creates an instance based on the given constructor.|
20| napi_get_new_target | Obtains the **new.target** of the constructor call.|
21| napi_define_class | Defines an ArkTS class corresponding to the C/C++ class. This API binds an ArkTS class and a C/C++ class.|
22| napi_wrap | Wraps a native object into an ArkTS object. This API allows the methods and properties of a native object to be called from ArkTS.|
23| napi_unwrap | Unwraps the native object from an ArkTS object.|
24| napi_remove_wrap | Removes the wrapping after the native object is unwrapped from an ArkTS object.|
25
26## Example
27
28If you are just starting out with Node-API, see [Node-API Development Process](use-napi-process.md). The following demonstrates only the C++ and ArkTS code involved in the class-related APIs.
29
30### napi_new_instance
31
32Use **napi_new_instance** to create an ArkTS instance with the given constructor. This API returns an instance that can be called from ArkTS.
33
34> **NOTE**
35>
36> If **constructor** is not of the function type, **napi_function_expected** will be returned.
37
38CPP code:
39
40```cpp
41static napi_value NewInstance(napi_env env, napi_callback_info info)
42{
43    // Pass in and parse parameters. The first parameter is the constructor, and the second parameter is the parameters of the constructor.
44    size_t argc = 2;
45    napi_value args[2] = {nullptr};
46    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
47    // Call napi_new_instance to create an instance and return the instance created.
48    napi_value result = nullptr;
49    napi_new_instance(env, args[0], 1, &args[1], &result);
50    return result;
51}
52```
53
54API declaration:
55
56```ts
57// index.d.ts
58export const newInstance: (obj: Object, param: string) => Object
59```
60
61ArkTS code:
62
63```ts
64import hilog from '@ohos.hilog'
65import testNapi from 'libentry.so'
66class Fruit {
67  name: string;
68  constructor(name: string) {
69    this.name = name;
70  }
71}
72// Call the function and use the variable obj to hold the instance created.
73let obj = testNapi.newInstance(Fruit, 'test');
74// Print the information about the object obj.
75hilog.info(0x0000, 'Node-API', 'napi_new_instance %{public}s', JSON.stringify(obj));
76```
77
78### napi_get_new_target
79
80Use **napi_get_new_target** to obtain **new.target** of a constructor. In ArkTS, **new.target** is a meta property used to determine whether a constructor was called using the **new** operator.
81
82For more information, see [Wrapping a Native Object in an ArkTS Object](use-napi-object-wrap.md).
83
84### napi_define_class
85
86Use **napi_define_class** to define an ArkTS class. This API creates an ArkTS class and associates the methods and properties of the ArkTS class with those of a C/C++ class.
87
88For more information, see [Wrapping a Native Object in an ArkTS Object](use-napi-object-wrap.md).
89
90### napi_wrap
91
92Use **napi_wrap** to wrap a native instance in an ArkTS object.
93
94> **NOTE**
95>
96> If **js_object** is not of the object or function type, **napi_object_expected** will be returned.
97
98### napi_unwrap
99
100Use **napi_unwrap** to unwrap a native instance from an ArkTS object and obtain the pointer to the data.
101
102> **NOTE**
103>
104> If **js_object** is not of the object or function type, **napi_object_expected** will be returned.
105
106### napi_remove_wrap
107
108Use **napi_remove_wrap** to remove the wrapping after a native instance is unwrapped from an ArkTS object.
109
110> **NOTE**
111>
112> If **js_object** is not of the object or function type, **napi_object_expected** will be returned.
113
114CPP code:
115
116```cpp
117#include <hilog/log.h>
118#include <string>
119#include "napi/native_api.h"
120
121struct Object {
122    std::string name;
123    int32_t age;
124};
125
126static void DerefItem(napi_env env, void *data, void *hint) {
127    // Optional native callback, which is used to release the native instance when the ArkTS object is garbage-collected.
128    OH_LOG_INFO(LOG_APP, "Node-API DerefItem");
129    (void)hint;
130}
131
132static napi_value Wrap(napi_env env, napi_callback_info info)
133{
134    OH_LOG_INFO(LOG_APP, "Node-API wrap");
135    // Initialize the native object.
136    struct Object *obj = new struct Object();
137    obj->name = "lilei";
138    obj->age = 18;
139    size_t argc = 1;
140    napi_value toWrap;
141    // Call napi_wrap to wrap the native object in an ArkTS object.
142    napi_get_cb_info(env, info, &argc, &toWrap, NULL, NULL);
143    napi_wrap(env, toWrap, reinterpret_cast<void *>(obj), DerefItem, NULL, NULL);
144
145    return toWrap;
146}
147
148static napi_value RemoveWrap(napi_env env, napi_callback_info info)
149{
150    OH_LOG_INFO(LOG_APP, "Node-API removeWrap");
151    size_t argc = 1;
152    napi_value wrapped = nullptr;
153    void *data = nullptr;
154    // Call napi_remove_wrap to remove the wrapping.
155    napi_get_cb_info(env, info, &argc, &wrapped, nullptr, nullptr);
156    napi_remove_wrap(env, wrapped, &data);
157
158    return nullptr;
159}
160
161static napi_value UnWrap(napi_env env, napi_callback_info info)
162{
163    OH_LOG_INFO(LOG_APP, "Node-API unWrap");
164    size_t argc = 1;
165    napi_value wrapped = nullptr;
166    napi_get_cb_info(env, info, &argc, &wrapped, nullptr, nullptr);
167    // Call napi_unwrap to retrieve the data from the ArkTS object and print the data.
168    struct Object *data;
169    napi_unwrap(env, wrapped, reinterpret_cast<void **>(&data));
170    OH_LOG_INFO(LOG_APP, "Node-API name: %{public}s", data->name.c_str());
171    OH_LOG_INFO(LOG_APP, "Node-API age: %{public}d", data->age);
172    return nullptr;
173}
174```
175
176API declaration:
177
178```ts
179// index.d.ts
180export const wrap: (obj: Object) => Object;
181export const unWrap: (obj: Object) => void;
182export const removeWrap: (obj: Object) => void;
183```
184
185ArkTS code:
186
187```ts
188import hilog from '@ohos.hilog'
189import testNapi from 'libentry.so'
190try {
191    class Obj {}
192    let obj: Obj = {};
193    testNapi.wrap(obj)
194    testNapi.unWrap(obj)
195    testNapi.removeWrap(obj)
196} catch (error) {
197    hilog.error(0x0000, 'testTag', 'Test Node-API error: %{public}s', error.message);
198}
199```
200
201To print logs in the native CPP, add the following information to the **CMakeLists.txt** file and add the header file by using **#include "hilog/log.h"**.
202
203```text
204// CMakeLists.txt
205add_definitions( "-DLOG_DOMAIN=0xd0d0" )
206add_definitions( "-DLOG_TAG=\"testTag\"" )
207target_link_libraries(entry PUBLIC libhilog_ndk.z.so)
208```
209