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