Skip to content

Commit 35c714f

Browse files
authored
examples to read and create Uint8Array (#197)
1 parent c0285f9 commit 35c714f

4 files changed

Lines changed: 151 additions & 0 deletions

File tree

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"targets": [
3+
{
4+
"target_name": "typed_array_to_native",
5+
"cflags!": [ "-fno-exceptions" ],
6+
"cflags_cc!": [ "-fno-exceptions" ],
7+
"sources": [ "typed_array_to_native.cc" ],
8+
"include_dirs": [
9+
"<!@(node -p \"require('node-addon-api').include\")"
10+
],
11+
'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],
12+
}
13+
]
14+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
const binding = require('bindings')('typed_array_to_native');
2+
3+
{
4+
const byteArray = Uint8Array.from([10, 20, 30, 50, 25, 17]);
5+
console.log("byteArray: ", byteArray);
6+
binding.AcceptByteArray(byteArray);
7+
}
8+
console.log("---------");
9+
10+
{
11+
const array = [7, 15, 26, 58, 64];
12+
console.log("array: ", array);
13+
const byteArray = binding.CreateByteArray(array);
14+
console.log("byteArray: ", byteArray);
15+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"name": "typed_array_to_native",
3+
"version": "0.0.0",
4+
"description": "Shows how to read and create typed arrays",
5+
"main": "index.js",
6+
"private": true,
7+
"dependencies": {
8+
"bindings": "~1.2.1",
9+
"node-addon-api": "^1.0.0"
10+
},
11+
"scripts": {
12+
"test": "node index.js"
13+
}
14+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
#include <napi.h>
2+
#include <cstdio>
3+
4+
static Napi::Value AcceptByteArray(const Napi::CallbackInfo& info) {
5+
if (info.Length() != 1) {
6+
Napi::Error::New(info.Env(), "Expected exactly one argument")
7+
.ThrowAsJavaScriptException();
8+
return info.Env().Undefined();
9+
}
10+
11+
if (!info[0].IsTypedArray()) {
12+
Napi::Error::New(info.Env(), "Expected a TypedArray")
13+
.ThrowAsJavaScriptException();
14+
return info.Env().Undefined();
15+
}
16+
Napi::TypedArray typedArray = info[0].As<Napi::TypedArray>();
17+
18+
if (typedArray.TypedArrayType() != napi_uint8_array) {
19+
Napi::Error::New(info.Env(), "Expected an Uint8Array")
20+
.ThrowAsJavaScriptException();
21+
return info.Env().Undefined();
22+
}
23+
Napi::Uint8Array uint8Array = typedArray.As<Napi::Uint8Array>();
24+
25+
// Copy to std::vector<uint8_t>:
26+
std::vector<uint8_t> bytes(uint8Array.Data(),
27+
uint8Array.Data() + uint8Array.ElementLength());
28+
printf("std::vector<uint8_t> from Uint8Array: [");
29+
for (uint8_t byte : bytes) {
30+
printf("%d, ", byte);
31+
}
32+
printf("\b\b]\n");
33+
34+
return info.Env().Undefined();
35+
}
36+
37+
static Napi::Value CreateByteArray(const Napi::CallbackInfo& info) {
38+
if (info.Length() != 1) {
39+
Napi::Error::New(info.Env(), "Expected exactly one argument")
40+
.ThrowAsJavaScriptException();
41+
return info.Env().Undefined();
42+
}
43+
44+
if (!info[0].IsArray()) {
45+
Napi::Error::New(info.Env(), "Expected an Array")
46+
.ThrowAsJavaScriptException();
47+
return info.Env().Undefined();
48+
}
49+
Napi::Array array = info[0].As<Napi::Array>();
50+
size_t arrayLength = array.Length();
51+
52+
// Create std::vector<uint8_t> out of array.
53+
// We allocate it on the heap to allow wrapping it up into ArrayBuffer.
54+
std::unique_ptr<std::vector<uint8_t>> nativeArray =
55+
std::make_unique<std::vector<uint8_t>>(arrayLength, 0);
56+
for (size_t i = 0; i < arrayLength; ++i) {
57+
Napi::Value arrayItem = array[i];
58+
if (!arrayItem.IsNumber()) {
59+
Napi::Error::New(info.Env(), "Expected a Number as Array Item")
60+
.ThrowAsJavaScriptException();
61+
return info.Env().Undefined();
62+
}
63+
Napi::Number number = arrayItem.As<Napi::Number>();
64+
double numberValue = number.DoubleValue();
65+
if (numberValue < 0 || numberValue > 255) {
66+
Napi::Error::New(info.Env(),
67+
"Array Item Number value is out of range [0..255]")
68+
.ThrowAsJavaScriptException();
69+
return info.Env().Undefined();
70+
}
71+
72+
(*nativeArray)[i] = static_cast<uint8_t>(numberValue);
73+
}
74+
75+
printf("std::vector<uint8_t> from Array: [");
76+
for (uint8_t byte : *nativeArray) {
77+
printf("%d, ", byte);
78+
}
79+
printf("\b\b]\n");
80+
81+
// Wrap up the std::vector into the ArrayBuffer.
82+
// Note: instead of wrapping the std::vector we could allow ArrayBuffer to
83+
// create internal storage that copies the std::vector, but it is less
84+
// efficient because it requires an extra memory allocation.
85+
Napi::ArrayBuffer arrayBuffer = Napi::ArrayBuffer::New(
86+
info.Env(),
87+
nativeArray->data(),
88+
arrayLength /* size in bytes */,
89+
[](Napi::Env /*env*/, void* /*data*/, std::vector<uint8_t>* hint) {
90+
std::unique_ptr<std::vector<uint8_t>> vectorPtrToDelete(hint);
91+
},
92+
nativeArray.get());
93+
// The finalizer is responsible for deleting the vector: release the
94+
// unique_ptr ownership.
95+
nativeArray.release();
96+
97+
Napi::Uint8Array byteArray = Napi::Uint8Array::New(info.Env(), arrayLength, arrayBuffer, 0);
98+
99+
return byteArray;
100+
}
101+
102+
static Napi::Object Init(Napi::Env env, Napi::Object exports) {
103+
exports["AcceptByteArray"] = Napi::Function::New(env, AcceptByteArray);
104+
exports["CreateByteArray"] = Napi::Function::New(env, CreateByteArray);
105+
return exports;
106+
}
107+
108+
NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)

0 commit comments

Comments
 (0)