1# Working with ArrayBuffer Using Node-API
2
3## Introduction
4
5**ArrayBuffer** in ArkTS is a type of object that represents a generic, fixed-length buffer of raw binary data. It provides a way to effectively represent and manipulate raw binary data in ArkTS.
6
7## Basic Concepts
8
9- **ArrayBuffer**: An **ArrayBuffer** object represents a generic, fixed-length buffer of raw binary data. The **ArrayBuffer** content cannot be directly operated. Instead, you need to use a **TypedArray** or **DataView** object to interpret the buffer data in specific formats. **ArrayBuffer** is used to process a large amount of binary data, such as files and network data packets.
10- Lifecycle and memory management: When using Node-API to process **ArrayBuffer** objects, note that the lifecycle of the created **arrayBufferPtr** is managed by the engine and cannot be deleted by users. Otherwise, a double free error may occur.
11
12## Available APIs
13
14The following table lists the APIs used to manipulate data of the **ArrayBuffer** type.
15
16| API| Description|
17| -------- | -------- |
18| napi_is_arraybuffer | Checks whether a value is an **ArrayBuffer** object. Note that this API cannot be used to check whether a value is a **TypedArray** object. To check whether a value is a **TypedArray** object, use **napi_is_typedarray**.|
19| napi_get_arraybuffer_info | Obtains information of an **ArrayBuffer** object, including the pointer to the data and the data length.|
20| napi_detach_arraybuffer | Detaches the underlying data from an **ArrayBuffer** object. After the data is detached, you can operate the data in C/C++.|
21| napi_is_detached_arraybuffer | Checks whether an **ArrayBuffer** object has been detached.|
22| napi_create_arraybuffer | Creates an ArkTS **ArrayBuffer** object with the specified byte length.|
23
24## Example
25
26If 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 related to **ArrayBuffer** management.
27
28### napi_is_arraybuffer
29
30Use **napi_is_arraybuffer** to check whether a JS value is an **ArrayBuffer** object.
31
32CPP code:
33
34```cpp
35#include "napi/native_api.h"
36
37static napi_value IsArrayBuffer(napi_env env, napi_callback_info info)
38{
39    // Obtain a parameter.
40    size_t argc = 1;
41    napi_value args[1] = {nullptr};
42    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
43    // Call napi_is_arraybuffer to check whether the input parameter is an **ArrayBuffer** object.
44    bool result = false;
45    napi_status status = napi_is_arraybuffer(env, args[0], &result);
46    if (status != napi_ok) {
47        napi_throw_error(env, nullptr, "Node-API napi_is_arraybuffer fail");
48        return nullptr;
49    }
50    // Convert the result to napi_value and return it.
51    napi_value returnValue = nullptr;
52    napi_get_boolean(env, result, &returnValue);
53    return returnValue;
54}
55```
56
57API declaration:
58
59```ts
60// index.d.ts
61export const isArrayBuffer: <T>(arrayBuffer: T) => boolean | void;
62```
63
64ArkTS code:
65
66```ts
67import hilog from '@ohos.hilog'
68import testNapi from 'libentry.so'
69try {
70  let value = new ArrayBuffer(1);
71  let data = "123";
72  hilog.info(0x0000, 'testTag', 'Test Node-API napi_is_arraybuffer: %{public}s', testNapi.isArrayBuffer(value));
73  hilog.info(0x0000, 'testTag', 'Test Node-API napi_is_arraybuffer: %{public}s', testNapi.isArrayBuffer(data));
74} catch (error) {
75  hilog.error(0x0000, 'testTag', 'Test Node-API napi_is_arraybuffer error: %{public}s', error.message);
76}
77```
78
79### napi_get_arraybuffer_info
80
81Use **napi_get_arraybuffer_info** to obtain the underlying data buffer and length of an **ArrayBuffer** object.
82
83CPP code:
84
85```cpp
86#include "napi/native_api.h"
87
88static napi_value GetArraybufferInfo(napi_env env, napi_callback_info info)
89{
90    size_t argc = 1;
91    napi_value args[1] = {nullptr};
92    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
93    // Check whether the parameter is an ArrayBuffer object.
94    bool isArraybuffer = false;
95    napi_is_arraybuffer(env, args[0], &isArraybuffer);
96    if (!isArraybuffer) {
97        napi_throw_type_error(env, nullptr, "Argument must be an ArrayBuffer");
98        return nullptr;
99    }
100
101    void *data = nullptr;
102    size_t byteLength = 0;
103    // Obtain the underlying data buffer and length of the ArrayBuffer object.
104    napi_status status = napi_get_arraybuffer_info(env, args[0], &data, &byteLength);
105    if (status != napi_ok) {
106        napi_throw_error(env, nullptr, "Failed to get ArrayBuffer info");
107        return nullptr;
108    }
109    // Create a result object.
110    napi_value result = nullptr;
111    napi_create_object(env, &result);
112    // Set the byte length property of the data buffer.
113    napi_value byteLengthValue = nullptr;
114    napi_create_uint32(env, byteLength, &byteLengthValue);
115    napi_set_named_property(env, result, "byteLength", byteLengthValue);
116    napi_value bufferData;
117    napi_create_arraybuffer(env, byteLength, &data, &bufferData);
118    napi_set_named_property(env, result, "buffer", bufferData);
119    return result;
120}
121```
122
123API declaration:
124
125```ts
126// index.d.ts
127export class ArrayBufferInfo {
128  byteLength: number;
129  buffer: Object;
130}
131export const getArraybufferInfo: (data: ArrayBuffer) => ArrayBufferInfo | void;
132```
133
134ArkTS code:
135
136```ts
137import hilog from '@ohos.hilog'
138import testNapi from 'libentry.so'
139
140const buffer = new ArrayBuffer(10);
141hilog.info(0x0000, 'testTag', 'Test Node-API get_arraybuffer_info:%{public}s ', JSON.stringify(testNapi.getArraybufferInfo(buffer)));
142```
143
144### napi_detach_arraybuffer
145
146Use **napi_detach_arraybuffer** to detach the underlying data from an **ArrayBuffer** object.
147
148### napi_is_detached_arraybuffer
149
150Use **napi_is_detached_arraybuffer** to check whether an **ArrayBuffer** object has been detached.
151
152CPP code:
153
154```cpp
155#include "napi/native_api.h"
156
157static napi_value DetachedArraybuffer(napi_env env, napi_callback_info info)
158{
159    // Call napi_detach_arraybuffer to detach the underlying data from an ArrayBuffer object.
160    size_t argc = 1;
161    napi_value args[1] = {nullptr};
162    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
163    napi_value arrayBuffer = args[0];
164    napi_detach_arraybuffer(env, arrayBuffer);
165    // Pass out the detached ArrayBuffer object.
166    return arrayBuffer;
167}
168
169static napi_value IsDetachedArraybuffer(napi_env env, napi_callback_info info)
170{
171    // Call napi_is_detached_arraybuffer to check whether the specified ArrayBuffer object has been detached.
172    size_t argc = 1;
173    napi_value args[1] = {nullptr};
174    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
175    napi_value arrayBuffer = args[0];
176    bool result = false;
177    napi_is_detached_arraybuffer(env, arrayBuffer, &result);
178    // Call napi_get_boolean to convert the return value to napi_value, and pass out the napi_value for printing.
179    napi_value returnValue;
180    napi_get_boolean(env, result, &returnValue);
181    return returnValue;
182}
183```
184
185API declaration:
186
187```ts
188// index.d.ts
189export const detachedArraybuffer: (buffer:ArrayBuffer) => ArrayBuffer;
190export const isDetachedArraybuffer: (arrarBeffer: ArrayBuffer) => boolean;
191```
192
193ArkTS code:
194
195```ts
196import hilog from '@ohos.hilog'
197import testNapi from 'libentry.so'
198try {
199  const bufferArray = new ArrayBuffer(8);
200  hilog.info(0x0000, 'testTag', 'Test Node-API napi_is_detached_arraybuffer one: %{public}s', testNapi.isDetachedArraybuffer(bufferArray));
201  hilog.info(0x0000, 'testTag', 'Test Node-API napi_is_detached_arraybuffer two: %{public}s ', testNapi.isDetachedArraybuffer(testNapi.detachedArraybuffer(bufferArray)));
202} catch (error) {
203  hilog.error(0x0000, 'testTag', 'Test Node-API napi_is_detached_arraybuffer error: %{public}s', error.message);
204}
205```
206
207### napi_create_arraybuffer
208
209Use **napi_create_arraybuffer** to create an ArkTS **ArrayBuffer** object with the specified byte length in C/C++. If the caller wants to directly operate the buffer, return the underlying buffer to the caller. To write data to this buffer from ArkTS, you need to create a **TypedArray** or **DataView** object.
210
211> **NOTE**
212>
213> If **byte_length** of **napi_create_arraybuffer** is **0** or an excessively large value, nullptr will be returned in **data**. Therefore, it is necessary to check whether **data** is empty before using it.
214
215CPP code:
216
217```cpp
218#include "napi/native_api.h"
219
220static napi_value CreateArraybuffer(napi_env env, napi_callback_info info)
221{
222    size_t argc = 1;
223    napi_value argv[1] = {nullptr};
224    napi_value result = nullptr;
225    // Parse the input parameters.
226    napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
227    int32_t value;
228    size_t length;
229    // Convert the parameter passed from ArkTS to the size_t type and use it as the parameter of napi_create_arraybuffer.
230    napi_get_value_int32(env, argv[0], &value);
231    length = size_t(value);
232    void *data;
233    // Create an ArrayBuffer object.
234    napi_create_arraybuffer(env, length, &data, &result);
235    if (data != nullptr) {
236        // Check data before using it for subsequent operations.
237    }
238    // Return the ArrayBuffer object.
239    return result;
240}
241```
242
243API declaration:
244
245```ts
246// index.d.ts
247export const createArraybuffer: (size: number) => ArrayBuffer;
248```
249
250ArkTS code:
251
252```ts
253import hilog from '@ohos.hilog'
254import testNapi from 'libentry.so'
255
256hilog.info(0x0000, 'testTag', 'Test Node-API napi_create_arraybuffer:%{public}s', testNapi.createArraybuffer(10).toString());
257```
258
259To 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"**.
260
261```text
262// CMakeLists.txt
263add_definitions( "-DLOG_DOMAIN=0xd0d0" )
264add_definitions( "-DLOG_TAG=\"testTag\"" )
265target_link_libraries(entry PUBLIC libhilog_ndk.z.so)
266```
267