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