5

I am trying to create a basic native node addon where a javascript array is passed from node and then processed in c++. The problem is I cannot figure out how to correctly pass the array. I can instantiate the array without issue but assigning it using info[0].as throws errors.

My c++ code is

#include <napi.h>

using namespace Napi;
using namespace std;

Value Add(const CallbackInfo& info) 
{
  Env env = info.Env();


  Array result = Napi::Array::New(env);
  Array a = info[0].As<Array>;

  double arg1 = info[1].As<Number>().DoubleValue();
  Number num = Napi::Number::New(env, 2 + arg1);

  return num;
}

The error I am getting is

../cppsrc/main.cpp: In function ‘Napi::Value Add(const Napi::CallbackInfo&)’:
../cppsrc/main.cpp:12:21: error: conversion from ‘<unresolved overloaded function type>’ to non-scalar type ‘Napi::Array’ requested
   Array a = info[0].As<Array>;
             ~~~~~~~~^~~~~~~~~

What is the correct way to pass an array to c++? Is it even possible?

ZachB
  • 13,051
  • 4
  • 61
  • 89
Root0x
  • 472
  • 1
  • 9
  • 28

4 Answers4

6

This works for me:

void runSetPropertyAsyncWorker(const CallbackInfo& info) 
{
    std::string path = info[0].As<Napi::String>();
    int property = info[1].As<Number>();
    int dataSize = info[2].As<Number>();
    Array b = info[3].As<Array>();
    for(int i = 0; i<b.Length(); i++)
    {
      Napi::Value v = b[i];
      if (v.IsNumber())
      {
        int value = (int)v.As<Napi::Number>();
        ...
        ...
      }
    }

    ...
    ...

    Function callback = info[4].As<Function>();
    AsyncWorker* asyncWorker = new SetPropertyAsyncWorker(callback, ...);
    asyncWorker->Queue();
}
Morten Frederiksen
  • 5,114
  • 1
  • 40
  • 72
3

Use Napi::Object. Napi::Array is actually inherited from Napi::Object.

You could replace the code Array a = info[0].As<Array>; with Array a = info[0].ToObject();.

You can then access the data members via Value operator[] (uint32_t index) const

Source: https://nodejs.github.io/node-addon-api/class_napi_1_1_object.html

Edit: Bonus feature, if an argument that is not an object is passed, this will automatically trigger an Error: Object Expected.

Luke
  • 565
  • 5
  • 19
1

error code here:

Array a = info[0].As<Array>;

which should be

Array a = info[0].As<Array>();
zyfyy
  • 323
  • 3
  • 10
0

I was not able to find a solution to the actual question of interacting with the Javascript object directly with node-addon-api. The Solution that I chose to go with is JSON.stringify any arrays or objects and then parse then in c++ is a library called rapid json. This proves to be the only way to interface with javascript objects that i've been able to find

Root0x
  • 472
  • 1
  • 9
  • 28
  • 2
    That is not true. Plus, it slows down the code dramatically because you will have to parse the JSON in c++. It is also not very convenient in JavaScript. – Luke Feb 18 '19 at 01:46
  • I understand it was not an ideal solution but it was the best i could come up with at the time. With the size of the data that I was working with it was not really a speed concern. Also rapid JSON is a very fast c++ json library. – Root0x Feb 19 '19 at 22:29