From 6891f30fd1f0291e41790a820552c3ac6298c617 Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Fri, 27 May 2022 07:22:21 -0700 Subject: [PATCH] examples to read and create Uint8Array --- .../node-addon-api/binding.gyp | 14 +++ typed_array_to_native/node-addon-api/index.js | 15 +++ .../node-addon-api/package.json | 14 +++ .../node-addon-api/typed_array_to_native.cc | 108 ++++++++++++++++++ 4 files changed, 151 insertions(+) create mode 100644 typed_array_to_native/node-addon-api/binding.gyp create mode 100644 typed_array_to_native/node-addon-api/index.js create mode 100644 typed_array_to_native/node-addon-api/package.json create mode 100644 typed_array_to_native/node-addon-api/typed_array_to_native.cc diff --git a/typed_array_to_native/node-addon-api/binding.gyp b/typed_array_to_native/node-addon-api/binding.gyp new file mode 100644 index 00000000..ef4bb4a9 --- /dev/null +++ b/typed_array_to_native/node-addon-api/binding.gyp @@ -0,0 +1,14 @@ +{ + "targets": [ + { + "target_name": "typed_array_to_native", + "cflags!": [ "-fno-exceptions" ], + "cflags_cc!": [ "-fno-exceptions" ], + "sources": [ "typed_array_to_native.cc" ], + "include_dirs": [ + " +#include + +static Napi::Value AcceptByteArray(const Napi::CallbackInfo& info) { + if (info.Length() != 1) { + Napi::Error::New(info.Env(), "Expected exactly one argument") + .ThrowAsJavaScriptException(); + return info.Env().Undefined(); + } + + if (!info[0].IsTypedArray()) { + Napi::Error::New(info.Env(), "Expected a TypedArray") + .ThrowAsJavaScriptException(); + return info.Env().Undefined(); + } + Napi::TypedArray typedArray = info[0].As(); + + if (typedArray.TypedArrayType() != napi_uint8_array) { + Napi::Error::New(info.Env(), "Expected an Uint8Array") + .ThrowAsJavaScriptException(); + return info.Env().Undefined(); + } + Napi::Uint8Array uint8Array = typedArray.As(); + + // Copy to std::vector: + std::vector bytes(uint8Array.Data(), + uint8Array.Data() + uint8Array.ElementLength()); + printf("std::vector from Uint8Array: ["); + for (uint8_t byte : bytes) { + printf("%d, ", byte); + } + printf("\b\b]\n"); + + return info.Env().Undefined(); +} + +static Napi::Value CreateByteArray(const Napi::CallbackInfo& info) { + if (info.Length() != 1) { + Napi::Error::New(info.Env(), "Expected exactly one argument") + .ThrowAsJavaScriptException(); + return info.Env().Undefined(); + } + + if (!info[0].IsArray()) { + Napi::Error::New(info.Env(), "Expected an Array") + .ThrowAsJavaScriptException(); + return info.Env().Undefined(); + } + Napi::Array array = info[0].As(); + size_t arrayLength = array.Length(); + + // Create std::vector out of array. + // We allocate it on the heap to allow wrapping it up into ArrayBuffer. + std::unique_ptr> nativeArray = + std::make_unique>(arrayLength, 0); + for (size_t i = 0; i < arrayLength; ++i) { + Napi::Value arrayItem = array[i]; + if (!arrayItem.IsNumber()) { + Napi::Error::New(info.Env(), "Expected a Number as Array Item") + .ThrowAsJavaScriptException(); + return info.Env().Undefined(); + } + Napi::Number number = arrayItem.As(); + double numberValue = number.DoubleValue(); + if (numberValue < 0 || numberValue > 255) { + Napi::Error::New(info.Env(), + "Array Item Number value is out of range [0..255]") + .ThrowAsJavaScriptException(); + return info.Env().Undefined(); + } + + (*nativeArray)[i] = static_cast(numberValue); + } + + printf("std::vector from Array: ["); + for (uint8_t byte : *nativeArray) { + printf("%d, ", byte); + } + printf("\b\b]\n"); + + // Wrap up the std::vector into the ArrayBuffer. + // Note: instead of wrapping the std::vector we could allow ArrayBuffer to + // create internal storage that copies the std::vector, but it is less + // efficient because it requires an extra memory allocation. + Napi::ArrayBuffer arrayBuffer = Napi::ArrayBuffer::New( + info.Env(), + nativeArray->data(), + arrayLength /* size in bytes */, + [](Napi::Env /*env*/, void* /*data*/, std::vector* hint) { + std::unique_ptr> vectorPtrToDelete(hint); + }, + nativeArray.get()); + // The finalizer is responsible for deleting the vector: release the + // unique_ptr ownership. + nativeArray.release(); + + Napi::Uint8Array byteArray = Napi::Uint8Array::New(info.Env(), arrayLength, arrayBuffer, 0); + + return byteArray; +} + +static Napi::Object Init(Napi::Env env, Napi::Object exports) { + exports["AcceptByteArray"] = Napi::Function::New(env, AcceptByteArray); + exports["CreateByteArray"] = Napi::Function::New(env, CreateByteArray); + return exports; +} + +NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)