1# 使用Node-API接口进行buffer相关开发 2 3## 简介 4 5在ArkTS中,Buffer是一种用于处理二进制数据的数据类型。 6 7## 基本概念 8 9使用Node-API接口进行buffer相关开发时,使用Buffer对象与ArkTS代码之间进行二进制数据的有效交互,以便在Node-API模块创建、操纵和传递Buffer对象到ArkTS,从而处理和传递二进制数据,比如文件I/O、网络传输等。 10 11- **Buffer对象**:用于表示一段二进制数据的对象。 12- **外部Buffer**:在Node-API模块中创建的Buffer,可以与现有的数据关联起来而不需要复制数据到新的Buffer中。 13 14## 场景和功能使用 15 16以下这些接口用于有效地与ArkTS层进行交互,这使Node-API模块能够更好地处理ArkTS层的二进制数据,比如处理文件I/O、网络传输等操作: 17| 接口 | 描述 | 18| -------- | -------- | 19| napi_create_buffer | 用于创建并获取一个指定大小的ArkTS Buffer。 | 20| napi_create_buffer_copy | 用于创建并获取一个指定大小的ArkTS Buffer,并以给定的入参数据对buffer的缓冲区进行初始化。 | 21| napi_create_external_buffer | 用于创建并获取一个指定大小的ArkTS Buffer,并以给定数据进行初始化,该接口可为Buffer附带额外数据。 | 22| napi_get_buffer_info | 获取ArkTS Buffer底层数据缓冲区及其长度。 | 23| napi_is_buffer | 判断给定ArkTS value是否为Buffer对象。 | 24| napi_create_external_arraybuffer | 用于分配一个附加有外部数据的ArkTS ArrayBuffer。外部ArrayBuffer是一个特殊类型的ArrayBuffer,它持有对外部数据的引用而不实际拥有数据存储。| 25 26## 使用示例 27 28Node-API接口开发流程参考[使用Node-API实现跨语言交互开发流程](use-napi-process.md),本文仅对接口对应C++及ArkTS相关代码进行展示。 29 30### napi_create_buffer 31 32此接口用于创建Buffer对象。Buffer对象是用于在Node-API模块中操作二进制数据的一种特殊类型。 33 34cpp部分代码 35 36```cpp 37#include <string> 38#include "napi/native_api.h" 39 40static napi_value CreateBuffer(napi_env env, napi_callback_info info) 41{ 42 std::string str("CreateBuffer"); 43 void *bufferPtr = nullptr; 44 size_t bufferSize = str.size(); 45 napi_value buffer = nullptr; 46 // 调用napi_create_buffer接口创建并获取一个指定大小的ArkTS Buffer 47 napi_create_buffer(env, bufferSize, &bufferPtr, &buffer); 48 // 将字符串str的值复制到buffer的内存中 49 strcpy((char *)bufferPtr, str.data()); 50 return buffer; 51} 52``` 53 54接口声明 55 56```ts 57// index.d.ts 58export const createBuffer: () => string; 59``` 60 61ArkTS侧示例代码 62 63```ts 64import hilog from '@ohos.hilog' 65import testNapi from 'libentry.so' 66try { 67 hilog.info(0x0000, 'testTag', 'Test Node-API napi_create_buffer: %{public}s', testNapi.createBuffer().toString()); 68} catch (error) { 69 hilog.error(0x0000, 'testTag', 'Test Node-API napi_create_buffer error'); 70} 71``` 72 73### napi_create_buffer_copy 74 75本接口是Node-API中用于创建并复制数据到Buffer对象的函数。它可以在Node-API模块中创建一个新的Buffer对象,并将指定的数据复制到该Buffer对象中。 76 77cpp部分代码 78 79```cpp 80#include <string> 81#include "hilog/log.h" 82#include "napi/native_api.h" 83 84static napi_value CreateBufferCopy(napi_env env, napi_callback_info info) 85{ 86 // 要copy的内容 87 std::string str("CreateBufferCopy"); 88 napi_value buffer = nullptr; 89 // 调用napi_create_buffer_copy接口创建buffer并将str的内容copy到buffer 90 void* resultData = nullptr; 91 napi_create_buffer_copy(env, str.size(), str.data(), &resultData, &buffer); 92 OH_LOG_INFO(LOG_APP, "Node-API resultData is : %{public}s.", resultData); 93 return buffer; 94} 95``` 96 97接口声明 98 99```ts 100// index.d.ts 101export const createBufferCopy: () => string; 102``` 103 104ArkTS侧示例代码 105 106```ts 107import hilog from '@ohos.hilog' 108import testNapi from 'libentry.so' 109try { 110 hilog.info(0x0000, 'testTag', 'Test Node-API napi_create_buffer_copy: %{public}s', testNapi.createBufferCopy().toString()); 111} catch (error) { 112 hilog.error(0x0000, 'testTag', 'Test Node-API napi_create_buffer_copy error'); 113} 114``` 115 116### napi_create_external_buffer 117 118当希望在ArkTS中使用现有的Node-API模块内存块,而不需要额外的拷贝时,可以使用napi_create_external_buffer。这将允许ArkTS层直接访问并操作该内存,避免额外的内存分配和拷贝操作。 119 120cpp部分代码 121 122```cpp 123#include <malloc.h> 124#include <string> 125#include "napi/native_api.h" 126 127// 回调函数,用于释放内存 128void FinalizeCallback(napi_env env, void *data, void *hint) 129{ 130 if (data == nullptr) { 131 return; 132 } 133 free(data); 134 data = nullptr; 135} 136 137static napi_value CreateExternalBuffer(napi_env env, napi_callback_info info) 138{ 139 // 创建一个字符串 140 std::string str("CreateExternalBuffer"); 141 // 在堆上分配内存,大小为字符串的长度 142 void* data = malloc(str.size()); 143 // 将字符串复制到分配的内存中 144 strcpy((char *)(data), (char*)(str.data())); 145 // 使用napi_create_external_buffer接口创建并获取一个指定大小buffer 146 napi_value buffer = nullptr; 147 napi_create_external_buffer(env, str.size(), data, FinalizeCallback, nullptr, &buffer); 148 return buffer; 149} 150``` 151 152接口声明 153 154```ts 155// index.d.ts 156export const createExternalBuffer: () => string; 157``` 158 159ArkTS侧示例代码 160 161```ts 162import hilog from '@ohos.hilog' 163import testNapi from 'libentry.so' 164try { 165 hilog.info(0x0000, 'testTag', 'Test Node-API napi_create_external_buffer: %{public}s', testNapi.createExternalBuffer() 166 .toString()); 167} catch (error) { 168 hilog.error(0x0000, 'testTag', 'Test Node-API napi_create_external_buffer error'); 169} 170``` 171 172### napi_get_buffer_info 173 174在ArkTS中需要对Buffer对象中的数据执行特定的操作时,可以使用此接口来获取指向数据的指针和数据长度。这样可以在Node-API模块直接对数据进行操作,而无需进行数据的拷贝。 175 176cpp部分代码 177 178```cpp 179#include <string> 180#include "napi/native_api.h" 181 182static napi_value GetBufferInfo(napi_env env, napi_callback_info info) 183{ 184 // 创建一个字符串 185 std::string str("GetBufferInfo"); 186 napi_value buffer = nullptr; 187 void *bufferPtr = nullptr; 188 size_t bufferSize = str.size(); 189 napi_create_buffer(env, bufferSize, &bufferPtr, &buffer); 190 strcpy((char *)bufferPtr, str.data()); 191 192 // 获取Buffer的信息 193 void *tmpBufferPtr = nullptr; 194 size_t bufferLength = 0; 195 napi_get_buffer_info(env, buffer, &tmpBufferPtr, &bufferLength); 196 197 // 创建一个新的ArkTS字符串来保存Buffer的内容并返出去 198 napi_value returnValue = nullptr; 199 napi_create_string_utf8(env, (char*)tmpBufferPtr, bufferLength, &returnValue); 200 return returnValue; 201} 202``` 203 204接口声明 205 206```ts 207// index.d.ts 208export const getBufferInfo: () => string; 209``` 210 211ArkTS侧示例代码 212 213```ts 214import hilog from '@ohos.hilog' 215import testNapi from 'libentry.so' 216try { 217 hilog.info(0x0000, 'testTag', 'Test Node-API napi_get_buffer_info: %{public}s', testNapi.getBufferInfo().toString()); 218} catch (error) { 219 hilog.error(0x0000, 'testTag', 'Test Node-API napi_get_buffer_info error'); 220} 221``` 222 223### napi_is_buffer 224 225判断给定ArkTS value是否为Buffer对象。 226 227cpp部分代码 228 229```cpp 230#include <string> 231#include "napi/native_api.h" 232 233static napi_value IsBuffer(napi_env env, napi_callback_info info) 234{ 235 // 创建一个Buffer对象 236 std::string str = "buffer"; 237 napi_value buffer = nullptr; 238 napi_create_buffer(env, strlen(str.data()), (void **)(str.data()), &buffer); 239 240 // 调用napi_is_buffer接口判断创建的对象是否为buffer 241 bool result = false; 242 napi_is_buffer(env, buffer, &result); 243 // 将结果返回出去 244 napi_value returnValue = nullptr; 245 napi_get_boolean(env, result, &returnValue); 246 return returnValue; 247} 248``` 249 250接口声明 251 252```ts 253// index.d.ts 254export const isBuffer: () => boolean; 255``` 256 257ArkTS侧示例代码 258 259```ts 260import hilog from '@ohos.hilog' 261import testNapi from 'libentry.so' 262try { 263 hilog.info(0x0000, 'testTag', 'Test Node-API napi_is_buffer: %{public}s', JSON.stringify(testNapi.isBuffer())); 264} catch (error) { 265 hilog.info(0x0000, 'testTag', 'Test Node-API napi_is_buffer error'); 266} 267``` 268 269### napi_create_external_arraybuffer 270 271分配一个附加有外部数据的ArkTS ArrayBuffer。 272 273cpp部分代码 274 275```cpp 276#include "napi/native_api.h" 277 278typedef struct { 279 uint8_t *data; 280 size_t length; 281} BufferData; 282 283void FinalizeCallback(napi_env env, void *finalize_data, void *finalize_hint) 284{ 285 // 获取终结时的数据 286 BufferData *bufferData = static_cast<BufferData *>(finalize_data); 287 288 // 执行清理操作,比如释放资源 289 delete[] bufferData->data; 290 delete bufferData; 291} 292 293napi_value CreateExternalArraybuffer(napi_env env, napi_callback_info info) 294{ 295 // 创建一个有五个元素的C++数组 296 uint8_t *dataArray = new uint8_t[5]{1, 2, 3, 4, 5}; 297 napi_value externalBuffer = nullptr; 298 BufferData *bufferData = new BufferData{dataArray, 5}; 299 300 // 使用napi_create_external_arraybuffer创建一个外部Array Buffer对象,并指定终结回调函数 301 napi_status status = 302 napi_create_external_arraybuffer(env, dataArray, 5, FinalizeCallback, bufferData, &externalBuffer); 303 if (status != napi_ok) { 304 // 处理错误 305 napi_throw_error(env, nullptr, "Node-API napi_create_external_arraybuffer fail"); 306 return nullptr; 307 } 308 napi_value outputArray; 309 // 使用napi_create_typedarray创建一个Array对象,并将externalBuffer对象作为参数传入 310 status = napi_create_typedarray(env, napi_int8_array, 5, externalBuffer, 0, &outputArray); 311 if (status != napi_ok) { 312 // 处理错误 313 napi_throw_error(env, nullptr, "Node-API napi_create_typedarray fail"); 314 return nullptr; 315 } 316 return outputArray; 317} 318``` 319 320接口声明 321 322```ts 323// index.d.ts 324export const createExternalArraybuffer: () => ArrayBuffer | void; 325``` 326 327ArkTS侧示例代码 328 329```ts 330import hilog from '@ohos.hilog' 331import testNapi from 'libentry.so' 332 333hilog.info(0x0000, 'testTag', 'Node-API createExternalArraybuffer: %{public}s', 334 JSON.stringify(testNapi.createExternalArraybuffer())); 335``` 336 337以上代码如果要在native cpp中打印日志,需在CMakeLists.txt文件中添加以下配置信息(并添加头文件:#include "hilog/log.h"): 338 339```text 340// CMakeLists.txt 341add_definitions( "-DLOG_DOMAIN=0xd0d0" ) 342add_definitions( "-DLOG_TAG=\"testTag\"" ) 343target_link_libraries(entry PUBLIC libhilog_ndk.z.so) 344``` 345