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