Tutorial to Native Node.js Modules with C++. Part 2 — Arrays, JSON and Callbacks

Jesus Christ, it’s JSON Bourne…

Vincent Mühler
3 min readOct 31, 2017

After reading Part 1 of this series you are probably thinking: “Damn, quite awesome how easy it is to write and compile my own native node module from C++ code. That’s all I need to know?” Well, it’s enough to get started. In Part 1 we have only been passing flat values and instances of our vector class back and forth. However, at some point you probably also want to pass arrays, JSON objects or functions to your C++ API. Therefore, its time to dig a little deeper.

In this article you can find a quick overview about how to:

  • pass JS arrays to a native addon and how to access its elements
  • pass JSON objects to the native addon and read its properties
  • create JS arrays and JSON objects from C++ and return them to your JS app
  • handle callbacks and invoke JS functions from C++

Dealing with arrays:

Unpacking arrays is pretty simple. We cast the v8::Value to an v8::Array, loop over the array and push every element into a std::vector, a simple collection, which is the C++ equivalent to an JS array or a List in Java if you want to see it that way.

Every element in the array is an v8::Value, which has to be unwrapped depending on whatever type it has. You could as well pass an array of class instances and unwrap each element as we did with Vectors in Part 1. You could also pass an array of JSON objects or an array of arrays. However, keep in mind that an JS array can hold elements of different types, as it is not typed as in C++.

Creating an array and returning it from a native function call can be achieved as follows:

Dealing with JSON:

Passing JSON objects to a function call can be particularly useful for configuration parameters and multiple return values.

Specifically, I found it useful to return a JSON object, holding the return values, when a function call has to return multiple stuff. In C++ you would have to pass the reference of every other return value as an argument to the function.

Furthermore it can be very convenient to pass optional parameters as a JSON object. This way the user of your API doesn’t have to retype and remember all default parameters, if they only want to adjust the parameters at the end of the function signature.

We can read properties of a JSON object, assuming an object with the keys ‘foo’ and ‘bar’ such as

{ foo: 123, bar: 'hi' }

like this:

Properties are accessed via v8::Strings. With Nan::HasOwnProperty(obj, key) we can check, whether the object actually has a certain property key before we access the value. Nan::Get will return the corresponding value, which we have to unwrap.

Creating a JSON object works the other way round. First we create a new object and then we set arbitrary properties as key value pairs on the object via Nan::Set(obj, key, value):

This should return the following JSON object:

{ foo: 456, bar: 'awesome' }

Using callbacks:

Callbacks are an essential part of the asynchronous programming model of JavaScript and likewise for Node.js. In Part 3 of this series I will show you how to write asynchronous bindings to your native node module via AsyncWorkers.

Furthermore callbacks can be used as a means to call a JS function from your C++ module. Let’s say we want to pass the following function:

function isFoo (str) {
return str === ‘foo’;
}

If we pass the function to the native call we can create a Nan::Callback from it and invoke it with cb.Call(argc, args):

Calling the function from C++ is done the exact same way as we did with calling the Vector constructor to create a new instance from C++ in Part 1. We have to pass the argument count argc and the arguments as an array of v8::Values. From cb.Call we retrieve the result e.g. the return value of our JS function as a v8::Value.

Need an introduction to developing native Node.js addons? Check out Part 1.

Want to build an asynchronous node module? Check out Part 3.

--

--