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