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