• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 使用Node-API接口进行ArrayBuffer相关开发
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
11ArrayBuffer是ArkTS中的一种数据类型,用于表示通用的、固定长度的原始二进制数据缓冲区。它提供了一种在ArkTS中有效地表示和操作原始二进制数据的方式。
12
13## 基本概念
14
15- **ArrayBuffer**:ArrayBuffer对象用来表示一个通用的、固定长度的原始二进制数据缓冲区。不能直接操作ArrayBuffer的内容,而是需要包装成TypedArray对象或DataView对象来读写。ArrayBuffer常用于处理大量的二进制数据,如文件、网络数据包等。
16
17## 场景和功能介绍
18
19以下Node-API接口用于操作ArrayBuffer类型的数据。
20
21| 接口 | 描述 |
22| -------- | -------- |
23| napi_is_arraybuffer | 检查一个值是否为ArrayBuffer,以确保正在处理正确的数据类型。需要注意的是,此函数只能判断一个值是否为ArrayBuffer,而不能判断一个值是否为TypedArray。要判断一个值是否为TypedArray,可以使用napi_is_typedarray函数。 |
24| napi_get_arraybuffer_info | 获取给定的ArrayBuffer对象的相关信息,包括数据指针和数据长度。 |
25| napi_detach_arraybuffer | 将ArrayBuffer底层缓冲区与ArrayBuffer对象分离。分离后可以直接在C/C++中操作数据,而无需通过Node-API接口进行数据访问。 |
26| napi_is_detached_arraybuffer | 判断给定的ArrayBuffer是否已经被分离。 |
27| napi_create_arraybuffer | 用于在Node-API模块中创建一个具有指定字节长度的ArkTS ArrayBuffer对象。 |
28
29## 使用示例
30
31Node-API接口开发流程参考[使用Node-API实现跨语言交互开发流程](use-napi-process.md),本文仅对接口对应C++及ArkTS相关代码进行展示。
32
33### napi_is_arraybuffer
34
35判断给定ArkTS value是否为ArrayBuffer。
36
37cpp部分代码
38
39```cpp
40#include "napi/native_api.h"
41
42static napi_value IsArrayBuffer(napi_env env, napi_callback_info info)
43{
44    // 接受一个入参
45    size_t argc = 1;
46    napi_value args[1] = {nullptr};
47    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
48    // 调用napi_is_arraybuffer接口判断给定入参是否为ArrayBuffer数据
49    bool result = false;
50    napi_status status = napi_is_arraybuffer(env, args[0], &result);
51    if (status != napi_ok) {
52        napi_throw_error(env, nullptr, "Node-API napi_is_arraybuffer fail");
53        return nullptr;
54    }
55    // 将结果转成napi_value类型返回
56    napi_value returnValue = nullptr;
57    napi_get_boolean(env, result, &returnValue);
58    return returnValue;
59}
60```
61<!-- @[napi_is_arraybuffer](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIArraybuffer/entry/src/main/cpp/napi_init.cpp) -->
62
63接口声明
64
65```ts
66// index.d.ts
67export const isArrayBuffer: <T>(arrayBuffer: T) => boolean | undefined;
68```
69<!-- @[napi_is_arraybuffer_api](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIArraybuffer/entry/src/main/cpp/types/libentry/Index.d.ts) -->
70
71ArkTS侧示例代码
72
73```ts
74import { hilog } from '@kit.PerformanceAnalysisKit';
75import testNapi from 'libentry.so';
76try {
77  let value = new ArrayBuffer(1);
78  let data = "123";
79  hilog.info(0x0000, 'testTag', 'Test Node-API napi_is_arraybuffer: %{public}s', testNapi.isArrayBuffer(value));
80  hilog.info(0x0000, 'testTag', 'Test Node-API napi_is_arraybuffer: %{public}s', testNapi.isArrayBuffer(data));
81} catch (error) {
82  hilog.error(0x0000, 'testTag', 'Test Node-API napi_is_arraybuffer error: %{public}s', error.message);
83}
84```
85<!-- @[ark_napi_is_arraybuffer](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIArraybuffer/entry/src/main/ets/pages/Index.ets) -->
86
87输出日志:
88
89Test Node-API napi_is_arraybuffer: true<br>
90Test Node-API napi_is_arraybuffer: false
91
92### napi_get_arraybuffer_info
93
94获取ArrayBuffer的底层数据缓冲区和长度。
95
96cpp部分代码
97
98```cpp
99#include "napi/native_api.h"
100#include <cstring>
101
102static napi_value GetArrayBufferInfo(napi_env env, napi_callback_info info)
103{
104    size_t argc = 1;
105    napi_value args[1] = {nullptr};
106    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
107    // 检查参数是否为ArrayBuffer
108    bool isArrayBuffer = false;
109    napi_is_arraybuffer(env, args[0], &isArrayBuffer);
110    if (!isArrayBuffer) {
111        napi_throw_type_error(env, nullptr, "Argument must be an ArrayBuffer");
112        return nullptr;
113    }
114
115    void *data = nullptr;
116    size_t byteLength = 0;
117    // 获取ArrayBuffer的底层数据缓冲区和长度
118    napi_status status = napi_get_arraybuffer_info(env, args[0], &data, &byteLength);
119    if (status != napi_ok) {
120        napi_throw_error(env, nullptr, "Failed to get ArrayBuffer info");
121        return nullptr;
122    }
123    // 创建结果对象
124    napi_value result = nullptr;
125    napi_create_object(env, &result);
126    // 创建数据缓冲区的字节长度属性
127    napi_value byteLengthValue = nullptr;
128    napi_create_uint32(env, byteLength, &byteLengthValue);
129    napi_set_named_property(env, result, "byteLength", byteLengthValue);
130    napi_value bufferData = nullptr;
131    void *newData = nullptr;
132    napi_create_arraybuffer(env, byteLength, &newData, &bufferData);
133    memcpy(newData, data, byteLength);
134    napi_set_named_property(env, result, "buffer", bufferData);
135    return result;
136}
137```
138<!-- @[napi_get_arraybuffer_info](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIArraybuffer/entry/src/main/cpp/napi_init.cpp) -->
139
140接口声明
141
142```ts
143// index.d.ts
144export class ArrayBufferInfo {
145  byteLength: number;
146  buffer: ArrayBuffer;
147}
148export const getArrayBufferInfo: (data: ArrayBuffer) => ArrayBufferInfo | undefined;
149```
150<!-- @[napi_get_arraybuffer_info_api](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIArraybuffer/entry/src/main/cpp/types/libentry/Index.d.ts) -->
151
152ArkTS侧示例代码
153
154```ts
155import { hilog } from '@kit.PerformanceAnalysisKit';
156import testNapi from 'libentry.so';
157
158try {
159  let typedArray = new Uint8Array([1, 2, 3, 4, 5]);
160  let buffer = typedArray.buffer;
161  let result = testNapi.getArrayBufferInfo(buffer) as testNapi.ArrayBufferInfo;
162  let resBuffer = new Uint8Array(result.buffer);
163  hilog.info(0x0000, 'testTag', 'Test Node-API get_arrayBuffer_info byteLength: %{public}d buffer: %{public}s', result.byteLength, JSON.stringify(resBuffer));
164} catch (error) {
165  hilog.error(0x0000, 'testTag', 'Test Node-API get_arrayBuffer_info error: %{public}s', error.message);
166}
167```
168<!-- @[ark_napi_get_arraybuffer_info](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIArraybuffer/entry/src/main/ets/pages/Index.ets) -->
169
170输出日志:
171
172Test Node-API get_arrayBuffer_info:{"byteLength":10,"buffer":{}}
173
174### napi_detach_arraybuffer
175
176分离给定ArrayBuffer的底层数据。
177
178### napi_is_detached_arraybuffer
179
180判断给定的ArrayBuffer是否已被分离。
181
182cpp部分代码
183
184```cpp
185#include "napi/native_api.h"
186
187static napi_value DetachedArrayBuffer(napi_env env, napi_callback_info info)
188{
189    // 调用napi_detach_arraybuffer接口分离给定ArrayBuffer的底层数据
190    size_t argc = 1;
191    napi_value args[1] = {nullptr};
192    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
193    napi_value arrayBuffer = args[0];
194    napi_detach_arraybuffer(env, arrayBuffer);
195    // 将分离后的arraybuffer传出去
196    return arrayBuffer;
197}
198
199static napi_value IsDetachedArrayBuffer(napi_env env, napi_callback_info info)
200{
201    // 调用napi_is_detached_arraybuffer判断给定的arraybuffer是否已被分离
202    size_t argc = 1;
203    napi_value args[1] = {nullptr};
204    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
205    napi_value arrayBuffer = args[0];
206    bool result = false;
207    napi_is_detached_arraybuffer(env, arrayBuffer, &result);
208    // 将返回值通过napi_get_boolean接口转成napi_value传出去做打印
209    napi_value returnValue;
210    napi_get_boolean(env, result, &returnValue);
211    return returnValue;
212}
213```
214<!-- @[napi_detach_arraybuffer](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIArraybuffer/entry/src/main/cpp/napi_init.cpp) -->
215
216接口声明
217
218```ts
219// index.d.ts
220export const detachedArrayBuffer: (buffer:ArrayBuffer) => ArrayBuffer;
221export const isDetachedArrayBuffer: (arrayBuffer: ArrayBuffer) => boolean;
222```
223<!-- @[napi_detach_arraybuffer_api](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIArraybuffer/entry/src/main/cpp/types/libentry/Index.d.ts) -->
224
225ArkTS侧示例代码
226
227```ts
228import { hilog } from '@kit.PerformanceAnalysisKit';
229import testNapi from 'libentry.so';
230try {
231  const bufferArray = new ArrayBuffer(8);
232  hilog.info(0x0000, 'testTag', 'Test Node-API napi_is_detached_arraybuffer one: %{public}s', testNapi.isDetachedArrayBuffer(bufferArray));
233  hilog.info(0x0000, 'testTag', 'Test Node-API napi_is_detached_arraybuffer two: %{public}s ', testNapi.isDetachedArrayBuffer(testNapi.detachedArrayBuffer(bufferArray)));
234} catch (error) {
235  hilog.error(0x0000, 'testTag', 'Test Node-API napi_is_detached_arraybuffer error: %{public}s', error.message);
236}
237```
238<!-- @[ark_napi_detach_arraybuffer](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIArraybuffer/entry/src/main/ets/pages/Index.ets) -->
239
240输出日志:
241
242Test Node-API napi_is_detached_arraybuffer one: false<br>
243Test Node-API napi_is_detached_arraybuffer two: true
244
245### napi_create_arraybuffer
246
247用于在C/C++中创建一个具有指定字节长度的ArkTS ArrayBuffer对象,如果调用者想要直接操作缓冲区,则可以选择将底层缓冲区返回给调用者。要从ArkTS写入此缓冲区,需要创建类型化数组或DataView对象。
248
249> **注意**
250>
251> napi_create_arraybuffer在byte_length为0或超大值时,data返回值将为nullptr。因此在对data进行使用前,有必要对其进行判空。
252
253cpp部分代码
254
255```cpp
256#include "napi/native_api.h"
257#include "hilog/log.h"
258
259static napi_value CreateArrayBuffer(napi_env env, napi_callback_info info)
260{
261    size_t argc = 1;
262    napi_value argv[1] = {nullptr};
263    napi_value result = nullptr;
264    // 解析传递的参数
265    napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
266    int32_t value;
267    size_t length;
268    // 将ArkTS侧传递的参数转换为size_t类型,作为napi_create_arraybuffer的参数
269    napi_get_value_int32(env, argv[0], &value);
270    length = size_t(value);
271    void *data = nullptr;
272    // 创建一个新的ArrayBuffer
273    napi_create_arraybuffer(env, length, &data, &result);
274    if (data != nullptr) {
275      // 确保安全后才能使用data进行操作
276    } else {
277      // 处理内存分配失败的情况
278      OH_LOG_ERROR(LOG_APP, "Failed to allocate memory for ArrayBuffer");
279      return nullptr;
280    }
281    // 返回ArrayBuffer
282    return result;
283}
284```
285<!-- @[napi_create_arraybuffer](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIArraybuffer/entry/src/main/cpp/napi_init.cpp) -->
286
287接口声明
288
289```ts
290// index.d.ts
291export const createArrayBuffer: (size: number) => ArrayBuffer;
292```
293<!-- @[napi_create_arraybuffer_api](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIArraybuffer/entry/src/main/cpp/types/libentry/Index.d.ts) -->
294
295ArkTS侧示例代码
296
297```ts
298import { hilog } from '@kit.PerformanceAnalysisKit';
299import testNapi from 'libentry.so';
300
301hilog.info(0x0000, 'testTag', 'Test Node-API napi_create_arraybuffer:%{public}s', testNapi.createArrayBuffer(10).toString());
302```
303<!-- @[ark_napi_create_arraybuffer](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPIArraybuffer/entry/src/main/ets/pages/Index.ets) -->
304
305以上代码如果要在native cpp中打印日志,需在CMakeLists.txt文件中添加以下配置信息(并添加头文件:#include "hilog/log.h"):
306
307```text
308// CMakeLists.txt
309add_definitions( "-DLOG_DOMAIN=0xd0d0" )
310add_definitions( "-DLOG_TAG=\"testTag\"" )
311target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so)
312```
313
314输出日志:
315Test Node-API napi_create_arraybuffer:[object ArrayBuffer]
316
317## 注意事项
318
319- **生命周期和内存管理**:在使用Node-API处理ArrayBuffer时,需注意,void*类型的buffer数据段生命周期由引擎管理,[不允许用户自己delete,否则会double free](napi-guidelines.md#防止重复释放获取的buffer)。
320- **需注意申请buff大小**:当byte_length很大时,分配失败并不会抛异常,参数data指向的内存为nullptr。建议对*data == nullptr做严格判断,并对超大byte_length做限额检验,避免OOM。
321