1# Working with Buffer Using Node-API
2
3## Introduction
4
5In ArkTS, **Buffer** is a data type used to represent binary data.
6
7## Basic Concepts
8
9Node-API provides APIs for handling binary data with ArkTS via the **Buffer** object. You can use these APIs to create, manipulate, and pass **Buffer** objects to ArkTS when processing and transferring binary data in file I/O and network transmission.
10
11- **Buffer** object: an object used to represent binary data.
12- External buffer: a buffer created in the Node-API module to associate with existing data without copying the data.
13
14## Available APIs
15
16The following table lists the APIs for processing the binary data in the ArkTS layer, such as file I/O and network transmission.
17| API| Description|
18| -------- | -------- |
19| napi_create_buffer | Creates an ArkTS **Buffer** instance of the specified size.|
20| napi_create_buffer_copy | Creates and obtains an ArkTS **Buffer** instance of the specified size and initializes the **Buffer** instance with the given parameters.|
21| napi_create_external_buffer | Creates an ArkTS **Buffer** instance of the specified size, and initializes it with the given data. You can use this API to add extra data to the buffer. |
22| napi_get_buffer_info | Obtains the underlying data of an ArkTS **Buffer** instance and its length.|
23| napi_is_buffer | Checks whether the given ArkTS value is a **Buffer** object.|
24| napi_create_external_arraybuffer | Creates an ArkTS external **ArrayBuffer**. An external **ArrayBuffer** is a special type of **ArrayBuffer** that holds the reference to external data without actually owning the data.|
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 related to **Buffer** management.
29
30### napi_create_buffer
31
32Use **napi_create_buffer** to create a **Buffer** instance. A **Buffer** object is used to manipulate binary data in C/C++.
33
34CPP code:
35
36```cpp
37#include <string>
38#include "napi/native_api.h"
39
40static napi_value CreateBuffer(napi_env env, napi_callback_info info)
41{
42    std::string str("CreateBuffer");
43    void *bufferPtr = nullptr;
44    size_t bufferSize = str.size();
45    napi_value buffer = nullptr;
46    // Call napi_create_buffer to create an ArkTS Buffer instance with the specified size.
47    napi_create_buffer(env, bufferSize, &bufferPtr, &buffer);
48    // Copy the value of str to the Buffer memory.
49    strcpy((char *)bufferPtr, str.data());
50    return buffer;
51}
52```
53
54API declaration:
55
56```ts
57// index.d.ts
58export const createBuffer: () => string;
59```
60
61ArkTS code:
62
63```ts
64import hilog from '@ohos.hilog'
65import testNapi from 'libentry.so'
66try {
67  hilog.info(0x0000, 'testTag', 'Test Node-API napi_create_buffer: %{public}s', testNapi.createBuffer().toString());
68} catch (error) {
69  hilog.error(0x0000, 'testTag', 'Test Node-API napi_create_buffer error');
70}
71```
72
73### napi_create_buffer_copy
74
75Use **napi_create_buffer_copy** to create a **Buffer** instance of the specified size and initialize it with data copied from the passed-in buffer. This API allows the specified data to be copied to a **Buffer** instance created.
76
77CPP code:
78
79```cpp
80#include <string>
81#include "hilog/log.h"
82#include "napi/native_api.h"
83
84static napi_value CreateBufferCopy(napi_env env, napi_callback_info info)
85{
86    // Data to copy.
87    std::string str("CreateBufferCopy");
88    napi_value buffer = nullptr;
89    // Call napi_create_buffer_copy to create a Buffer instance and copy the content of str to the Buffer.
90    void* resultData = nullptr;
91    napi_create_buffer_copy(env, str.size(), str.data(), &resultData, &buffer);
92    OH_LOG_INFO(LOG_APP, "Node-API resultData is : %{public}s.", resultData);
93    return buffer;
94}
95```
96
97API declaration:
98
99```ts
100// index.d.ts
101export const createBufferCopy: () => string;
102```
103
104ArkTS code:
105
106```ts
107import hilog from '@ohos.hilog'
108import testNapi from 'libentry.so'
109try {
110  hilog.info(0x0000, 'testTag', 'Test Node-API napi_create_buffer_copy: %{public}s', testNapi.createBufferCopy().toString());
111} catch (error) {
112  hilog.error(0x0000, 'testTag', 'Test Node-API napi_create_buffer_copy error');
113}
114```
115
116### napi_create_external_buffer
117
118Use **napi_create_external_buffer** to create an ArkTS **Buffer** instance that holds a pointer to existing data. This allows the data to be directly accessed and manipulated from ArkTS, improving performance while avoiding additional memory allocation and data copy.
119
120CPP code:
121
122```cpp
123#include <malloc.h>
124#include <string>
125#include "napi/native_api.h"
126
127// Callback used to release memory.
128void FinalizeCallback(napi_env env, void *data, void *hint)
129{
130    if (data == nullptr) {
131        return;
132    }
133    free(data);
134    data = nullptr;
135}
136
137static napi_value CreateExternalBuffer(napi_env env, napi_callback_info info)
138{
139    // Create a string.
140    std::string str("CreateExternalBuffer");
141    // Allocate memory of the string length on the heap.
142    void* data = malloc(str.size());
143    // Copy the string to the allocated memory.
144    strcpy((char *)(data), (char*)(str.data()));
145    // Use napi_create_external_buffer to create a Buffer instance of the specified size.
146    napi_value buffer = nullptr;
147    napi_create_external_buffer(env, str.size(), data, FinalizeCallback, nullptr, &buffer);
148    return buffer;
149}
150```
151
152API declaration:
153
154```ts
155// index.d.ts
156export const createExternalBuffer: () => string;
157```
158
159ArkTS code:
160
161```ts
162import hilog from '@ohos.hilog'
163import testNapi from 'libentry.so'
164try {
165  hilog.info(0x0000, 'testTag', 'Test Node-API napi_create_external_buffer: %{public}s', testNapi.createExternalBuffer()
166    .toString());
167} catch (error) {
168  hilog.error(0x0000, 'testTag', 'Test Node-API napi_create_external_buffer error');
169}
170```
171
172### napi_get_buffer_info
173
174Before performing an operation on the data in a **Buffer** instance in ArkTS, use **napi_get_buffer_info** to obtain the pointer to the data and the data length. This allows the data to be operated without copying data.
175
176CPP code:
177
178```cpp
179#include <string>
180#include "napi/native_api.h"
181
182static napi_value GetBufferInfo(napi_env env, napi_callback_info info)
183{
184    // Create a string.
185    std::string str("GetBufferInfo");
186    napi_value buffer = nullptr;
187    void *bufferPtr = nullptr;
188    size_t bufferSize = str.size();
189    napi_create_buffer(env, bufferSize, &bufferPtr, &buffer);
190    strcpy((char *)bufferPtr, str.data());
191
192    // Obtain the Buffer information.
193    void *tmpBufferPtr = nullptr;
194    size_t bufferLength = 0;
195    napi_get_buffer_info(env, buffer, &tmpBufferPtr, &bufferLength);
196
197    // Create an ArkTS string to save the Buffer content and return it.
198    napi_value returnValue = nullptr;
199    napi_create_string_utf8(env, (char*)tmpBufferPtr, bufferLength, &returnValue);
200    return returnValue;
201}
202```
203
204API declaration:
205
206```ts
207// index.d.ts
208export const getBufferInfo: () => string;
209```
210
211ArkTS code:
212
213```ts
214import hilog from '@ohos.hilog'
215import testNapi from 'libentry.so'
216try {
217  hilog.info(0x0000, 'testTag', 'Test Node-API napi_get_buffer_info: %{public}s', testNapi.getBufferInfo().toString());
218} catch (error) {
219  hilog.error(0x0000, 'testTag', 'Test Node-API napi_get_buffer_info error');
220}
221```
222
223### napi_is_buffer
224
225Use **napi_is_buffer** to check whether an ArkTS value is a **Buffer** object.
226
227CPP code:
228
229```cpp
230#include <string>
231#include "napi/native_api.h"
232
233static napi_value IsBuffer(napi_env env, napi_callback_info info)
234{
235    // Create a Buffer object.
236    std::string str = "buffer";
237    napi_value buffer = nullptr;
238    napi_create_buffer(env, strlen(str.data()), (void **)(str.data()), &buffer);
239
240    //Call napi_is_buffer to check whether the created object is a Buffer.
241    bool reslut = false;
242    napi_is_buffer(env, buffer, &reslut);
243    // Return the result.
244    napi_value returnValue = nullptr;
245    napi_get_boolean(env, reslut, &returnValue);
246    return returnValue;
247}
248```
249
250API declaration:
251
252```ts
253// index.d.ts
254export const isBuffer: () => boolean;
255```
256
257ArkTS code:
258
259```ts
260import hilog from '@ohos.hilog'
261import testNapi from 'libentry.so'
262try {
263  hilog.info(0x0000, 'testTag', 'Test Node-API napi_is_buffer: %{public}s', JSON.stringify(testNapi.isBuffer()));
264} catch (error) {
265  hilog.info(0x0000, 'testTag', 'Test Node-API napi_is_buffer error');
266}
267```
268
269### napi_create_external_arraybuffer
270
271Use **napi_create_external_arraybuffer** to create an ArkTS **ArrayBuffer** with external data.
272
273CPP code:
274
275```cpp
276#include "napi/native_api.h"
277
278typedef struct {
279    uint8_t *data;
280    size_t length;
281} BufferData;
282
283void FinalizeCallback(napi_env env, void *finalize_data, void *finalize_hint)
284{
285    // Obtain the finalized data.
286    BufferData *bufferData = static_cast<BufferData *>(finalize_data);
287
288    // Perform the cleanup operation, for example, release memory.
289    delete[] bufferData->data;
290    delete bufferData;
291}
292
293napi_value CreateExternalArraybuffer(napi_env env, napi_callback_info info)
294{
295    // Create a C++ array with five elements.
296    uint8_t *dataArray = new uint8_t[5]{1, 2, 3, 4, 5};
297    napi_value externalBuffer = nullptr;
298    BufferData *bufferData = new BufferData{dataArray, 5};
299
300    // Call napi_create_external_arraybuffer to create an external ArrayBuffer instance and specify the callback to be invoked when the ArrayBuffer object is garbage-collected.
301    napi_status status =
302        napi_create_external_arraybuffer(env, dataArray, 5, FinalizeCallback, bufferData, &externalBuffer);
303    if (status != napi_ok) {
304        // Error handling.
305        napi_throw_error(env, nullptr, "Node-API napi_create_external_arraybuffer fail");
306        return nullptr;
307    }
308    napi_value outputArray;
309    // Use napi_create_typedarray to create a TypedArray object and pass the external buffer object as a parameter.
310    status = napi_create_typedarray(env, napi_int8_array, 5, externalBuffer, 0, &outputArray);
311    if (status != napi_ok) {
312        // Error handling.
313        napi_throw_error(env, nullptr, "Node-API napi_create_typedarray fail");
314        return nullptr;
315    }
316    return outputArray;
317}
318```
319
320API declaration:
321
322```ts
323// index.d.ts
324export const createExternalArraybuffer: () => ArrayBuffer | void;
325```
326
327ArkTS code:
328
329```ts
330import hilog from '@ohos.hilog'
331import testNapi from 'libentry.so'
332
333hilog.info(0x0000, 'testTag', 'Node-API createExternalArraybuffer: %{public}s',
334           JSON.stringify(testNapi.createExternalArraybuffer()));
335```
336
337To 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"**.
338
339```text
340// CMakeLists.txt
341add_definitions( "-DLOG_DOMAIN=0xd0d0" )
342add_definitions( "-DLOG_TAG=\"testTag\"" )
343target_link_libraries(entry PUBLIC libhilog_ndk.z.so)
344```
345