Node-API provides APIs for handling binary data with ArkTS via the Buffer object. You can use these APIs to create and operate Buffer objects, processing binary data in I/O and network transmission.
The following table lists the APIs for processing the binary data in the ArkTS layer, such as file I/O and network transmission.
| API | Description |
|---|---|
| napi_create_buffer | Creates an ArkTS Buffer instance of the specified size. |
| napi_create_buffer_copy | Creates and obtains an ArkTS Buffer instance of the specified size and initializes the Buffer instance with the given parameters. |
| napi_create_external_buffer | Creates an ArkTS Buffer instance of the specified size, and initializes it with the given data. You can use this API to add extra data to the buffer. |
| napi_get_buffer_info | Obtains the underlying data buffer and its length of an ArkTS Buffer instance. |
| napi_is_buffer | Checks whether the given ArkTS value is a Buffer object. |
| napi_create_external_arraybuffer | Creates an ArkTS external ArrayBuffer. An external ArrayBuffer is a special type of ArrayBuffer that holds the reference to external data without actually owning the data. |
If you are just starting out with Node-API, see Node-API Development Process. The following demonstrates only the C++ and ArkTS code related to Buffer management.
Call napi_create_buffer to create a Buffer instance. A Buffer object is used to manipulate binary data in C/C++.
CPP code:
// napi_create_buffer
static napi_value CreateBuffer(napi_env env, napi_callback_info info)
{
std::string str("CreateBuffer");
void *bufferPtr = nullptr;
size_t bufferSize = str.size();
napi_value buffer = nullptr;
// Call the napi_create_buffer API to create and obtain an ArkTS Buffer of a specified size.
napi_status status = napi_create_buffer(env, bufferSize + 1, &bufferPtr, &buffer);
if (status != napi_ok) {
OH_LOG_ERROR(LOG_APP, "napi_create_buffer failed");
return nullptr;
}
// Copy the value of the string str to the buffer's memory.
strcpy((char *)bufferPtr, str.data());
return buffer;
} API declaration:
export const createBuffer: () => string; // napi_create_buffer
ArkTS code:
// napi_create_buffer
try {
hilog.info(0x0000, 'testTag', 'Test Node-API napi_create_buffer: %{public}s',
testNapi.createBuffer().toString());
// ...
} catch (error) {
hilog.error(0x0000, 'testTag', 'Test Node-API napi_create_buffer error');
// ...
} Call napi_create_buffer_copy to create a Buffer instance of the specified size and initialize it with data copied from the passed-in buffer. This API allows the specified data to be copied to a Buffer instance created.
CPP code:
// napi_create_buffer_copy
static napi_value CreateBufferCopy(napi_env env, napi_callback_info info)
{
// Content to be copied.
char str[] = "CreateBufferCopy";
napi_value buffer = nullptr;
// Call the napi_create_buffer_copy API to create a buffer and copy the content of str to the buffer.
void* resultData = nullptr;
napi_status status = napi_create_buffer_copy(env, sizeof(str), str, &resultData, &buffer);
if (status != napi_ok) {
OH_LOG_ERROR(LOG_APP, "napi_create_buffer_copy failed");
return nullptr;
}
if (resultData != nullptr) {
OH_LOG_INFO(LOG_APP, "Node-API resultData is : %{public}s.", reinterpret_cast <const char*>(resultData));
} else {
OH_LOG_INFO(LOG_APP, "Node-API resultData is nullptr.");
}
return buffer;
} API declaration:
export const createBufferCopy: () => string; // napi_create_buffer_copy
ArkTS code:
// napi_create_buffer_copy
try {
hilog.info(0x0000, 'testTag', 'Test Node-API napi_create_buffer_copy: %{public}s',
testNapi.createBufferCopy().toString());
// ...
} catch (error) {
hilog.error(0x0000, 'testTag', 'Test Node-API napi_create_buffer_copy error');
// ...
} Call napi_create_external_buffer to create an ArkTS Buffer instance that holds a pointer to existing data. This allows the ArkTS layer to directly access and operate the memory, avoiding additional memory allocation and copy operations.
CPP code:
// Callback function used to release memory.
void FinalizeCallback(napi_env env, void *data, void *hint)
{
if (data == nullptr) {
return;
}
free(data);
data = nullptr;
}
// napi_create_external_buffer
static napi_value CreateExternalBuffer(napi_env env, napi_callback_info info)
{
// Create a string.
std::string str("CreateExternalBuffer");
// Allocate memory on the heap, with the size equal to the string length.
void* data = malloc(str.size() + 1);
if (data == nullptr) {
OH_LOG_ERROR(LOG_APP, "malloc failed");
return nullptr;
}
memset(data, 0, str.size() + 1);
// Copy the string to the allocated memory.
strcpy(static_cast<char *>(data), str.data());
// Use the napi_create_external_buffer API to create and obtain a buffer of a specified size.
napi_value buffer = nullptr;
napi_status status = napi_create_external_buffer(env, str.size(), data, FinalizeCallback, nullptr, &buffer);
if (status != napi_ok) {
free(data);
OH_LOG_ERROR(LOG_APP, "napi_create_external_buffer failed");
return nullptr;
}
return buffer;
} API declaration:
export const createExternalBuffer: () => string; // napi_create_external_buffer
ArkTS code:
// napi_create_external_buffer
try {
hilog.info(0x0000, 'testTag', 'Test Node-API napi_create_external_buffer: %{public}s',
testNapi.createExternalBuffer()
.toString());
// ...
} catch (error) {
hilog.error(0x0000, 'testTag', 'Test Node-API napi_create_external_buffer error');
// ...
} Before performing an operation on the data in a Buffer instance in ArkTS, use napi_get_buffer_info to obtain the pointer to the data and the data length. This allows the data to be operated without copying data.
CPP code:
// napi_get_buffer_info
static napi_value GetBufferInfo(napi_env env, napi_callback_info info)
{
// Create a string.
std::string str("GetBufferInfo");
napi_value buffer = nullptr;
void *bufferPtr = nullptr;
size_t bufferSize = str.size();
napi_status status = napi_create_buffer(env, bufferSize + 1, &bufferPtr, &buffer);
if (status != napi_ok) {
OH_LOG_ERROR(LOG_APP, "napi_create_buffer failed");
return nullptr;
}
strcpy((char *)bufferPtr, str.data());
// Obtain the Buffer information.
void *tmpBufferPtr = nullptr;
size_t bufferLength = 0;
napi_get_buffer_info(env, buffer, &tmpBufferPtr, &bufferLength);
// Create a new ArkTS string to hold the Buffer content and return it.
if (bufferLength == 0 || ((char*)tmpBufferPtr)[bufferLength - 1] != '\0') {
OH_LOG_ERROR(LOG_APP, "Buffer is not null-terminated");
return nullptr;
}
napi_value returnValue = nullptr;
napi_create_string_utf8(env, (char*)tmpBufferPtr, bufferLength, &returnValue);
return returnValue;
} API declaration:
export const getBufferInfo: () => string; // napi_get_buffer_info
ArkTS code:
// napi_get_buffer_info
try {
hilog.info(0x0000, 'testTag', 'Test Node-API napi_get_buffer_info: %{public}s',
testNapi.getBufferInfo().toString());
// ...
} catch (error) {
hilog.error(0x0000, 'testTag', 'Test Node-API napi_get_buffer_info error');
// ...
} Call napi_is_buffer to check whether an ArkTS value is a Buffer object.
CPP code:
// napi_is_buffer
static napi_value IsBuffer(napi_env env, napi_callback_info info)
{
// Create a Buffer object.
std::string str = "buffer";
napi_value buffer = nullptr;
void *bufferPtr = nullptr;
napi_create_buffer(env, str.size(), &bufferPtr, &buffer);
// Call the napi_is_buffer API to determine whether the created object is a buffer.
bool result = false;
napi_is_buffer(env, buffer, &result);
// Return the result.
napi_value returnValue = nullptr;
napi_get_boolean(env, result, &returnValue);
return returnValue;
} API declaration:
export const isBuffer: () => boolean; // napi_is_buffer
ArkTS code:
// napi_is_buffer
try {
hilog.info(0x0000, 'testTag', 'Test Node-API napi_is_buffer: %{public}s',
JSON.stringify(testNapi.isBuffer()));
// ...
} catch (error) {
hilog.info(0x0000, 'testTag', 'Test Node-API napi_is_buffer error');
// ...
} Call napi_create_external_arraybuffer to create an ArkTS ArrayBuffer with external data.
CPP code:
static constexpr int INT_ARG_5 = 5; // Input parameter index.
typedef struct {
uint8_t *data;
size_t length;
} BufferData;
void FinalizeCallback1(napi_env env, void *finalizeData, void *finalizeHint)
{
// Obtain the data upon finalization.
BufferData *bufferData = static_cast<BufferData *>(finalizeHint);
// Perform cleanup operations, such as releasing resources.
delete[] bufferData->data;
delete bufferData;
}
// napi_create_external_arraybuffer
napi_value CreateExternalArraybuffer(napi_env env, napi_callback_info info)
{
// Create a C++ array with five elements.
uint8_t *dataArray = new uint8_t[5]{1, 2, 3, 4, 5};
napi_value externalBuffer = nullptr;
BufferData *bufferData = new BufferData{dataArray, 5};
// Use napi_create_external_arraybuffer to create an external ArrayBuffer object and specify the finalization callback.
napi_status status =
napi_create_external_arraybuffer(env, dataArray, INT_ARG_5, FinalizeCallback1, bufferData, &externalBuffer);
if (status != napi_ok) {
// Handle the error.
delete[] dataArray;
delete bufferData;
napi_throw_error(env, nullptr, "Node-API napi_create_external_arraybuffer fail");
return nullptr;
}
napi_value outputArray;
// Use napi_create_typedarray to create an Array object, passing the externalBuffer object as a parameter.
status = napi_create_typedarray(env, napi_int8_array, INT_ARG_5, externalBuffer, 0, &outputArray);
if (status != napi_ok) {
// Handle the error.
napi_throw_error(env, nullptr, "Node-API napi_create_typedarray fail");
return nullptr;
}
return outputArray;
} API declaration:
export const createExternalArraybuffer: () => ArrayBuffer | undefined; // napi_create_external_arraybuffer
ArkTS code:
// napi_create_external_arraybuffer
hilog.info(0x0000, 'testTag', 'Node-API createExternalArraybuffer: %{public}s',
JSON.stringify(testNapi.createExternalArraybuffer())); To print logs in the native CPP, add the following information to the CMakeLists.txt file and add the header file by using #include "hilog/log.h".
// CMakeLists.txt add_definitions( "-DLOG_DOMAIN=0xd0d0" ) add_definitions( "-DLOG_TAG=\"testTag\"" ) target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so)