package.json

It’s almost always easier to set up your addon as an independent module. When done this way, you can require it from your local project, and a standard npm install will handle the entire build process.

Three key things happen in package.json:

Set gypfile totrue so npm install builds the addon automatically.

Set the entry point to the executable (“my_addon” below will be whatever you name your addon).

bindings.gyp

The binding file is where you define your build. If you only have one C++ file, and it’s platform independent (doesn’t use OS calls), then this is really straightforward. Make sure you use the right name for your addon - what you put for “my_addon” needs to match what you put in package.json, and in the C++ code below).

If you are feeling adventurous, check out the gyp documentation for all the options and use cases - however there is some chromium-only information there, so beware.

Passing data between C++ and JavaScript

The following demonstrates passing several primitive types to C++ from JavaScript, and synchronously returning primitives back to JavaScript. It uses NAN, which is the recommended approach for addon development.

Numeric data

// contents of addon_source.cc
// This is a basic addon - a binding.gyp file
// would need to include this file as it's source.
#include <nan.h>
usingnamespacestd;usingnamespaceNan;usingnamespacev8;// Accepts 1 number from JavaScript, adds 42 and returns the result.
NAN_METHOD(PassNumber){Nan::Maybe<double>value=Nan::To<double>(info[0]);Local<Number>retval=Nan::New(value.FromJust()+42);info.GetReturnValue().Set(retval);}// Called by the NODE_MODULE macro below,
// exposes a pass_number method to JavaScript, which maps to PassNumber
// above.
NAN_MODULE_INIT(Init){Nan::Set(target,New<String>("pass_number").ToLocalChecked(),GetFunction(New<FunctionTemplate>(PassNumber)).ToLocalChecked());}// macro to load the module when require'd
NODE_MODULE(my_addon,Init)

The following JavaScript program requires the addon above (see the beginning of this guide for setting this up).

String data

String data uses a slightly different syntax…

// contents of addon_source.cc
// Reverses the string given
NAN_METHOD(PassString){if(info.Length()<1){return;}if(!info[0]->IsString()){return;}// wrap the string with v8's string type
v8::String::Utf8Valueval(info[0]->ToString());// use it as a standard C++ string
std::stringstr(*val);std::reverse(str.begin(),str.end());info.GetReturnValue().Set(Nan::New<String>(str.c_str()).ToLocalChecked());}

Strings are pretty loosely interpreted. If you remove the info[0]->IsString() check in the C++
and pass in undefined, you’ll get denifednu back!

Objects

Objects are a little more complicated. Here, pass object accepts an object with two properties, X and Y. It returns a new object with the sum and product. Most of the code is really dedicated to creating the necessary strings to serve as property names.

// contents of addon_source.cc
NAN_METHOD(PassObject){if(info.Length()>0){Local<Object>input=info[0]->ToObject();// Make property names to access the input object
Local<String>x_prop=Nan::New<String>("x").ToLocalChecked();Local<String>y_prop=Nan::New<String>("y").ToLocalChecked();Local<String>sum_prop=Nan::New<String>("sum").ToLocalChecked();Local<String>product_prop=Nan::New<String>("product").ToLocalChecked();// create the return object
Local<Object>retval=Nan::New<Object>();// pull x and y out of the input. We'll get NaN if these weren't set,
// or if x / y aren't able to be converted to numbers.
doublex=Nan::Get(input,x_prop).ToLocalChecked()->NumberValue();doubley=Nan::Get(input,y_prop).ToLocalChecked()->NumberValue();// set the properties on the return object
Nan::Set(retval,sum_prop,Nan::New<Number>(x+y));Nan::Set(retval,product_prop,Nan::New<Number>(x*y));info.GetReturnValue().Set(retval);}}

If you are looking to work with Object Wrapping, where you can deal with C++ objects within JavaScript, take a look at the Node.js and C++ Integration book. The book also has a more complete set of examples of building objects inside V8 using Nan. For working directly with V8 without NAN, check out this post - it’s worth checking out!

Arrays

Finally, here’s an example of doing some work with arrays. Like object, arrays are mutable from within the addon - meaning if you change a property/index on the parameter, that change is happening on the actual JavaScript memory.

// contents of addon_source.cc
// Increment each value in the array parameter,
// Return a new array with the squares of the original
// array and a "sum_of_squares" property.
NAN_METHOD(IncrementArray){Local<Array>array=Local<Array>::Cast(info[0]);Local<String>ss_prop=Nan::New<String>("sum_of_squares").ToLocalChecked();Local<Array>squares=New<v8::Array>(array->Length());doubless=0;for(unsignedinti=0;i<array->Length();i++){if(Nan::Has(array,i).FromJust()){// get data from a particular index
doublevalue=Nan::Get(array,i).ToLocalChecked()->NumberValue();// set a particular index - note the array parameter
// is mutable
Nan::Set(array,i,Nan::New<Number>(value+1));Nan::Set(squares,i,Nan::New<Number>(value*value));ss+=value*value;}}// set a non index property on the returned array.
Nan::Set(squares,ss_prop,Nan::New<Number>(ss));info.GetReturnValue().Set(squares);}

What else should you know?

There are bunch more topics that you’ll need to learn before really being able to take full advantage C++ from Node.js. Here are a few important topics, and some resources on this site for learning them.

Asynchronous addons methods: Most addon methods shouldn’t block the event loop when called, which means you should make them asynchronous - they will accept a callback which will be used to return the results of the call. You can start learning the asynchronous pattern here, and using NAN with async is covered here. You’ll also want to check out streaming data from C++ to Node.js, which extends the asynchronous model.

Using Buffer objects: You need to be mindful of copying data between V8 and C++ proper, you can incur some penalties you might not expect. In addition, memory management and multithreading (asynchronous addons) can be tricky. Check out my article on how not to share memory between async threads, and learn about using buffers to side step this issue and save yourself a lot of memory copying.

Deploying addons: You can publish addons to the npm registry just like any other module, but when you do this it means the C++ code in your addon needs to be built on the target machine, using a C++ compiler. If that’s an issue, check out using node-pre-gyp to publish and distribute binaries for your supported platforms. While your at it, check out deploying your addons to Amazon Lambda too!

Looking for more?

Sign up to for Node Addons newsletter so you find out when new articles are published right away. With your signup, you'll get a free copy of Chapter 2 - Understanding V8 Programming from the Node and C++ Integration e-book