1# 使用Node-API接口进行ArrayBuffer相关开发
2
3## 简介
4
5ArrayBuffer是ArkTS中的一种数据类型,用于表示通用的、固定长度的原始二进制数据缓冲区。它提供了一种在ArkTS中有效地表示和操作原始二进制数据的方式。
6
7## 基本概念
8
9- **ArrayBuffer**:ArrayBuffer对象用来表示一个通用的、固定长度的原始二进制数据缓冲区。不能直接操作ArrayBuffer的内容,而是需要包装成TypedArray对象或DataView对象来读写。ArrayBuffer常用于处理大量的二进制数据,如文件、网络数据包等。
10- **生命周期和内存管理**:在使用Node-API处理ArrayBuffer时,需注意创建的arrayBufferPtr生命周期由引擎管理,不允许用户自己delete,否则会double free。
11
12## 场景和功能介绍
13
14以下Node-API接口通常在Node-API模块中操作ArrayBuffer类型的数据。以下是一些可能的使用场景:
15
16| 接口 | 描述 |
17| -------- | -------- |
18| napi_is_arraybuffer | 检查一个值是否为ArrayBuffer,以确保正在处理正确的数据类型。需要注意的是,此函数只能判断一个值是否为ArrayBuffer,而不能判断一个值是否为TypedArray。如果需要判断一个值是否为TypedArray,可以使用napi_is_typedarray函数。 |
19| napi_get_arraybuffer_info | 获取给定的ArrayBuffer对象的相关信息,包括数据指针和数据长度。 |
20| napi_detach_arraybuffer | 在某些情况下,当需要频繁地访问ArrayBuffer的底层数据缓冲区时,将其分离可以提高性能。分离后可以直接在C/C++中操作数据,而无需通过Node-API接口进行数据访问。 |
21| napi_is_detached_arraybuffer | 判断给定的ArrayBuffer是否已经被分离。 |
22| napi_create_arraybuffer | 用于在Node-API模块中创建一个具有指定字节长度的ArkTS ArrayBuffer对象。 |
23
24## 使用示例
25
26Node-API接口开发流程参考[使用Node-API实现跨语言交互开发流程](use-napi-process.md),本文仅对接口对应C++及ArkTS相关代码进行展示。
27
28### napi_is_arraybuffer
29
30判断给定ArkTS value是否为ArrayBuffer。
31
32cpp部分代码
33
34```cpp
35#include "napi/native_api.h"
36
37static napi_value IsArrayBuffer(napi_env env, napi_callback_info info)
38{
39    // 接受一个入参
40    size_t argc = 1;
41    napi_value args[1] = {nullptr};
42    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
43    // 调用napi_is_arraybuffer接口判断给定入参是否为ArrayBuffer数据
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    // 将结果转成napi_value类型返回
51    napi_value returnValue = nullptr;
52    napi_get_boolean(env, result, &returnValue);
53    return returnValue;
54}
55```
56
57接口声明
58
59```ts
60// index.d.ts
61export const isArrayBuffer: <T>(arrayBuffer: T) => boolean | void;
62```
63
64ArkTS侧示例代码
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
81获取ArrayBuffer的底层数据缓冲区和长度。
82
83cpp部分代码
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    // 检查参数是否为ArrayBuffer
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    // 获取ArrayBuffer的底层数据缓冲区和长度
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    // 创建结果对象
110    napi_value result = nullptr;
111    napi_create_object(env, &result);
112    // 创建数据缓冲区的字节长度属性
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
123接口声明
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侧示例代码
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
146分离给定ArrayBuffer的底层数据。
147
148### napi_is_detached_arraybuffer
149
150判断给定的ArrayBuffer是否已被分离。
151
152cpp部分代码
153
154```cpp
155#include "napi/native_api.h"
156
157static napi_value DetachedArrayBuffer(napi_env env, napi_callback_info info)
158{
159    // 调用napi_detach_arraybuffer接口分离给定ArrayBuffer的底层数据
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    // 将分离后的arraybuffer传出去
166    return arrayBuffer;
167}
168
169static napi_value IsDetachedArrayBuffer(napi_env env, napi_callback_info info)
170{
171    // 调用napi_is_detached_arraybuffer判断给定的arraybuffer是否已被分离
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    // 将返回值通过napi_get_boolean接口转成napi_value传出去做打印
179    napi_value returnValue;
180    napi_get_boolean(env, result, &returnValue);
181    return returnValue;
182}
183```
184
185接口声明
186
187```ts
188// index.d.ts
189export const detachedArrayBuffer: (buffer:ArrayBuffer) => ArrayBuffer;
190export const isDetachedArrayBuffer: (arrayBuffer: ArrayBuffer) => boolean;
191```
192
193ArkTS侧示例代码
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
209用于在C/C++中创建一个具有指定字节长度的ArkTS ArrayBuffer对象,如果调用者想要直接操作缓冲区,则可以选择将底层缓冲区返回给调用者。要从ArkTS写入此缓冲区,需要创建类型化数组或DataView对象。
210
211> **注意**
212>
213> napi_create_arraybuffer在byte_length为0或超大值时,data返回值将为nullptr。因此在对data进行使用前,有必要对其进行判空。
214
215cpp部分代码
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    // 解析传递的参数
226    napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
227    int32_t value;
228    size_t length;
229    // 将ArkTS侧传递的参数转换为size_t类型,作为napi_create_arraybuffer的参数
230    napi_get_value_int32(env, argv[0], &value);
231    length = size_t(value);
232    void *data;
233    // 创建一个新的ArrayBuffer
234    napi_create_arraybuffer(env, length, &data, &result);
235    if (data != nullptr) {
236        // 确保安全后才能使用data进行操作
237    }
238    // 返回ArrayBuffer
239    return result;
240}
241```
242
243接口声明
244
245```ts
246// index.d.ts
247export const createArrayBuffer: (size: number) => ArrayBuffer;
248```
249
250ArkTS侧示例代码
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
259以上代码如果要在native cpp中打印日志,需在CMakeLists.txt文件中添加以下配置信息(并添加头文件:#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