• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 使用Node-API接口进行buffer相关开发
2<!--Kit: NDK-->
3<!--Subsystem: arkcompiler-->
4<!--Owner: @xliu-huanwei; @shilei123; @huanghello-->
5<!--Designer: @shilei123-->
6<!--Tester: @kirl75; @zsw_zhushiwei-->
7<!--Adviser: @fang-jinxu-->
8
9## 简介
10
11在ArkTS中,Buffer是一种用于处理二进制数据的数据类型。
12
13## 基本概念
14
15使用Node-API接口进行buffer相关开发时,使用Buffer对象与ArkTS代码之间进行二进制数据的有效交互,以便在Node-API模块创建、操纵和传递Buffer对象到ArkTS,从而处理和传递二进制数据,比如文件I/O、网络传输等。
16
17- **Buffer对象**:用于表示一段二进制数据的对象。
18- **外部Buffer**:在Node-API模块中创建的Buffer,可以与现有的数据关联起来而不需要复制数据到新的Buffer中。
19
20## 场景和功能使用
21
22以下这些接口用于有效地与ArkTS层进行交互,这使Node-API模块能够更好地处理ArkTS层的二进制数据,比如处理文件I/O、网络传输等操作:
23| 接口 | 描述 |
24| -------- | -------- |
25| napi_create_buffer | 用于创建并获取一个指定大小的ArkTS Buffer。 |
26| napi_create_buffer_copy | 用于创建并获取一个指定大小的ArkTS Buffer,并以给定的入参数据对buffer的缓冲区进行初始化。 |
27| napi_create_external_buffer | 用于创建并获取一个指定大小的ArkTS Buffer,并以给定数据进行初始化,该接口可为Buffer附带额外数据。 |
28| napi_get_buffer_info | 获取ArkTS Buffer底层数据缓冲区及其长度。 |
29| napi_is_buffer | 判断给定ArkTS value是否为Buffer对象。 |
30| napi_create_external_arraybuffer | 用于分配一个附加有外部数据的ArkTS ArrayBuffer。外部ArrayBuffer是一个特殊类型的ArrayBuffer,它持有对外部数据的引用而不实际拥有数据存储。|
31
32## 使用示例
33
34Node-API接口开发流程参考[使用Node-API实现跨语言交互开发流程](use-napi-process.md),本文仅对接口对应C++及ArkTS相关代码进行展示。
35
36### napi_create_buffer
37
38此接口用于创建Buffer对象。Buffer对象是用于在Node-API模块中操作二进制数据的一种特殊类型。
39
40cpp部分代码
41
42```cpp
43#include <string>
44#include "hilog/log.h"
45#include "napi/native_api.h"
46
47static napi_value CreateBuffer(napi_env env, napi_callback_info info)
48{
49    std::string str("CreateBuffer");
50    void *bufferPtr = nullptr;
51    size_t bufferSize = str.size();
52    napi_value buffer = nullptr;
53    // 调用napi_create_buffer接口创建并获取一个指定大小的ArkTS Buffer
54    napi_status status = napi_create_buffer(env, bufferSize + 1, &bufferPtr, &buffer);
55    if (status != napi_ok) {
56        OH_LOG_ERROR(LOG_APP, "napi_create_buffer failed");
57        return nullptr;
58    }
59    // 将字符串str的值复制到buffer的内存中
60    strcpy((char *)bufferPtr, str.data());
61    return buffer;
62}
63```
64<!-- @[napi_create_buffer](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIBuffer/entry/src/main/cpp/napi_init.cpp) -->
65
66接口声明
67
68```ts
69// index.d.ts
70export const createBuffer: () => string;
71```
72<!-- @[napi_create_buffer_api](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIBuffer/entry/src/main/cpp/types/libentry/Index.d.ts) -->
73
74ArkTS侧示例代码
75
76```ts
77import { hilog } from '@kit.PerformanceAnalysisKit';
78import testNapi from 'libentry.so';
79try {
80  hilog.info(0x0000, 'testTag', 'Test Node-API napi_create_buffer: %{public}s', testNapi.createBuffer().toString());
81} catch (error) {
82  hilog.error(0x0000, 'testTag', 'Test Node-API napi_create_buffer error');
83}
84```
85<!-- @[ark_napi_create_buffer](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIBuffer/entry/src/main/ets/pages/Index.ets) -->
86
87### napi_create_buffer_copy
88
89本接口是Node-API中用于创建并复制数据到Buffer对象的函数。它可以在Node-API模块中创建一个新的Buffer对象,并将指定的数据复制到该Buffer对象中。
90
91cpp部分代码
92
93```cpp
94#include <string>
95#include "hilog/log.h"
96#include "napi/native_api.h"
97
98static napi_value CreateBufferCopy(napi_env env, napi_callback_info info)
99{
100    // 要copy的内容
101    char str[] = "CreateBufferCopy";
102    napi_value buffer = nullptr;
103    // 调用napi_create_buffer_copy接口创建buffer并将str的内容copy到buffer
104    void* resultData = nullptr;
105    napi_status status = napi_create_buffer_copy(env, sizeof(str), str, &resultData, &buffer);
106    if (status != napi_ok) {
107        OH_LOG_ERROR(LOG_APP, "napi_create_buffer_copy failed");
108        return nullptr;
109    }
110    if (resultData != nullptr) {
111        OH_LOG_INFO(LOG_APP, "Node-API resultData is : %{public}s.", reinterpret_cast <const char*>(resultData));
112    } else {
113        OH_LOG_INFO(LOG_APP, "Node-API resultData is nullptr.");
114    }
115    return buffer;
116}
117```
118<!-- @[napi_create_buffer_copy](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIBuffer/entry/src/main/cpp/napi_init.cpp) -->
119
120接口声明
121
122```ts
123// index.d.ts
124export const createBufferCopy: () => string;
125```
126<!-- @[napi_create_buffer_copy_api](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIBuffer/entry/src/main/cpp/types/libentry/Index.d.ts) -->
127
128ArkTS侧示例代码
129
130```ts
131import { hilog } from '@kit.PerformanceAnalysisKit';
132import testNapi from 'libentry.so';
133try {
134  hilog.info(0x0000, 'testTag', 'Test Node-API napi_create_buffer_copy: %{public}s', testNapi.createBufferCopy().toString());
135} catch (error) {
136  hilog.error(0x0000, 'testTag', 'Test Node-API napi_create_buffer_copy error');
137}
138```
139<!-- @[ark_napi_create_buffer_copy](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIBuffer/entry/src/main/ets/pages/Index.ets) -->
140
141### napi_create_external_buffer
142
143当希望在ArkTS中使用现有的Node-API模块内存块,而不需要额外的拷贝时,可以使用napi_create_external_buffer。这将允许ArkTS层直接访问并操作该内存,避免额外的内存分配和拷贝操作。
144
145cpp部分代码
146
147```cpp
148#include <cstdlib>
149#include <string>
150#include <hilog/log.h>
151#include "napi/native_api.h"
152
153// 回调函数,用于释放内存
154void FinalizeCallback(napi_env env, void *data, void *hint)
155{
156    if (data == nullptr) {
157        return;
158    }
159    free(data);
160    data = nullptr;
161}
162
163static napi_value CreateExternalBuffer(napi_env env, napi_callback_info info)
164{
165    // 创建一个字符串
166    std::string str("CreateExternalBuffer");
167    // 在堆上分配内存,大小为字符串的长度
168    void* data = malloc(str.size() + 1);
169    if (data == nullptr) {
170        OH_LOG_ERROR(LOG_APP, "malloc failed");
171        return nullptr;
172    }
173    memset(data, 0, str.size() + 1);
174    // 将字符串复制到分配的内存中
175    strcpy((char *)(data), (char*)(str.data()));
176    // 使用napi_create_external_buffer接口创建并获取一个指定大小buffer
177    napi_value buffer = nullptr;
178    napi_status status = napi_create_external_buffer(env, str.size(), data, FinalizeCallback, nullptr, &buffer);
179    if (status != napi_ok) {
180        free(data);
181        OH_LOG_ERROR(LOG_APP, "napi_create_external_buffer failed");
182        return nullptr;
183    }
184    return buffer;
185}
186```
187<!-- @[napi_create_external_buffer](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIBuffer/entry/src/main/cpp/napi_init.cpp) -->
188
189接口声明
190
191```ts
192// index.d.ts
193export const createExternalBuffer: () => string;
194```
195<!-- @[napi_create_external_buffer_api](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIBuffer/entry/src/main/cpp/types/libentry/Index.d.ts) -->
196
197ArkTS侧示例代码
198
199```ts
200import { hilog } from '@kit.PerformanceAnalysisKit';
201import testNapi from 'libentry.so';
202try {
203  hilog.info(0x0000, 'testTag', 'Test Node-API napi_create_external_buffer: %{public}s', testNapi.createExternalBuffer()
204    .toString());
205} catch (error) {
206  hilog.error(0x0000, 'testTag', 'Test Node-API napi_create_external_buffer error');
207}
208```
209<!-- @[ark_napi_create_external_buffer](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIBuffer/entry/src/main/ets/pages/Index.ets) -->
210
211### napi_get_buffer_info
212
213在ArkTS中需要对Buffer对象中的数据执行特定的操作时,可以使用此接口来获取指向数据的指针和数据长度。这样可以在Node-API模块直接对数据进行操作,而无需进行数据的拷贝。
214
215cpp部分代码
216
217```cpp
218#include <string>
219#include "hilog/log.h"
220#include "napi/native_api.h"
221
222static napi_value GetBufferInfo(napi_env env, napi_callback_info info)
223{
224    // 创建一个字符串
225    std::string str("GetBufferInfo");
226    napi_value buffer = nullptr;
227    void *bufferPtr = nullptr;
228    size_t bufferSize = str.size();
229    napi_status status = napi_create_buffer(env, bufferSize + 1, &bufferPtr, &buffer);
230    if (status != napi_ok) {
231        OH_LOG_ERROR(LOG_APP, "napi_create_buffer failed");
232        return nullptr;
233    }
234    strcpy((char *)bufferPtr, str.data());
235
236    // 获取Buffer的信息
237    void *tmpBufferPtr = nullptr;
238    size_t bufferLength = 0;
239    napi_get_buffer_info(env, buffer, &tmpBufferPtr, &bufferLength);
240
241    // 创建一个新的ArkTS字符串来保存Buffer的内容并返出去
242    if (bufferLength == 0 || ((char*)tmpBufferPtr)[bufferLength - 1] != '\0') {
243        OH_LOG_ERROR(LOG_APP, "Buffer is not null-terminated");
244        return nullptr;
245    }
246    napi_value returnValue = nullptr;
247    napi_create_string_utf8(env, (char*)tmpBufferPtr, bufferLength, &returnValue);
248    return returnValue;
249}
250```
251<!-- @[napi_get_buffer_info](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIBuffer/entry/src/main/cpp/napi_init.cpp) -->
252
253接口声明
254
255```ts
256// index.d.ts
257export const getBufferInfo: () => string;
258```
259<!-- @[napi_get_buffer_info_api](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIBuffer/entry/src/main/cpp/types/libentry/Index.d.ts) -->
260
261ArkTS侧示例代码
262
263```ts
264import { hilog } from '@kit.PerformanceAnalysisKit';
265import testNapi from 'libentry.so';
266try {
267  hilog.info(0x0000, 'testTag', 'Test Node-API napi_get_buffer_info: %{public}s', testNapi.getBufferInfo().toString());
268} catch (error) {
269  hilog.error(0x0000, 'testTag', 'Test Node-API napi_get_buffer_info error');
270}
271```
272<!-- @[ark_napi_get_buffer_info](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIBuffer/entry/src/main/ets/pages/Index.ets) -->
273
274### napi_is_buffer
275
276判断给定ArkTS value是否为Buffer对象。
277
278cpp部分代码
279
280```cpp
281#include <string>
282#include "napi/native_api.h"
283
284static napi_value IsBuffer(napi_env env, napi_callback_info info)
285{
286    // 创建一个Buffer对象
287    std::string str = "buffer";
288    napi_value buffer = nullptr;
289    void *bufferPtr = nullptr;
290    napi_create_buffer(env, str.size(), &bufferPtr, &buffer);
291
292    // 调用napi_is_buffer接口判断创建的对象是否为buffer
293    bool result = false;
294    napi_is_buffer(env, buffer, &result);
295    // 将结果返回出去
296    napi_value returnValue = nullptr;
297    napi_get_boolean(env, result, &returnValue);
298    return returnValue;
299}
300```
301<!-- @[napi_is_buffer](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIBuffer/entry/src/main/cpp/napi_init.cpp) -->
302
303接口声明
304
305```ts
306// index.d.ts
307export const isBuffer: () => boolean;
308```
309<!-- @[napi_is_buffer_api](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIBuffer/entry/src/main/cpp/types/libentry/Index.d.ts) -->
310
311ArkTS侧示例代码
312
313```ts
314import { hilog } from '@kit.PerformanceAnalysisKit';
315import testNapi from 'libentry.so';
316try {
317  hilog.info(0x0000, 'testTag', 'Test Node-API napi_is_buffer: %{public}s', JSON.stringify(testNapi.isBuffer()));
318} catch (error) {
319  hilog.info(0x0000, 'testTag', 'Test Node-API napi_is_buffer error');
320}
321```
322<!-- @[ark_napi_is_buffer](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIBuffer/entry/src/main/ets/pages/Index.ets) -->
323
324### napi_create_external_arraybuffer
325
326分配一个附加有外部数据的ArkTS ArrayBuffer。
327
328cpp部分代码
329
330```cpp
331#include "napi/native_api.h"
332
333typedef struct {
334    uint8_t *data;
335    size_t length;
336} BufferData;
337
338void FinalizeCallback(napi_env env, void *finalize_data, void *finalize_hint)
339{
340    // 获取终结时的数据
341    BufferData *bufferData = static_cast<BufferData *>(finalize_hint);
342
343    // 执行清理操作,比如释放资源
344    delete[] bufferData->data;
345    delete bufferData;
346}
347
348napi_value CreateExternalArraybuffer(napi_env env, napi_callback_info info)
349{
350    // 创建一个有五个元素的C++数组
351    uint8_t *dataArray = new uint8_t[5]{1, 2, 3, 4, 5};
352    napi_value externalBuffer = nullptr;
353    BufferData *bufferData = new BufferData{dataArray, 5};
354
355    // 使用napi_create_external_arraybuffer创建一个外部Array Buffer对象,并指定终结回调函数
356    napi_status status =
357        napi_create_external_arraybuffer(env, dataArray, 5, FinalizeCallback, bufferData, &externalBuffer);
358    if (status != napi_ok) {
359        // 处理错误
360        napi_throw_error(env, nullptr, "Node-API napi_create_external_arraybuffer fail");
361        return nullptr;
362    }
363    napi_value outputArray;
364    // 使用napi_create_typedarray创建一个Array对象,并将externalBuffer对象作为参数传入
365    status = napi_create_typedarray(env, napi_int8_array, 5, externalBuffer, 0, &outputArray);
366    if (status != napi_ok) {
367        // 处理错误
368        napi_throw_error(env, nullptr, "Node-API napi_create_typedarray fail");
369        return nullptr;
370    }
371    return outputArray;
372}
373```
374<!-- @[napi_create_external_arraybuffer](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIBuffer/entry/src/main/cpp/napi_init.cpp) -->
375
376接口声明
377
378```ts
379// index.d.ts
380export const createExternalArraybuffer: () => ArrayBuffer | undefined;
381```
382<!-- @[napi_create_external_arraybuffer_api](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIBuffer/entry/src/main/cpp/types/libentry/Index.d.ts) -->
383
384ArkTS侧示例代码
385
386```ts
387import { hilog } from '@kit.PerformanceAnalysisKit';
388import testNapi from 'libentry.so';
389
390hilog.info(0x0000, 'testTag', 'Node-API createExternalArraybuffer: %{public}s',
391           JSON.stringify(testNapi.createExternalArraybuffer()));
392```
393<!-- @[ark_napi_create_external_arraybuffer](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIBuffer/entry/src/main/ets/pages/Index.ets) -->
394
395以上代码如果要在native cpp中打印日志,需在CMakeLists.txt文件中添加以下配置信息(并添加头文件:#include "hilog/log.h"):
396
397```text
398// CMakeLists.txt
399add_definitions( "-DLOG_DOMAIN=0xd0d0" )
400add_definitions( "-DLOG_TAG=\"testTag\"" )
401target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so)
402```
403