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