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