C++ and Node.js: An Unholy Combination….But Oh So Right

Update for May 2016: Please note that this article is now 2 1/2 years old and was done with Node v0.8. Unfortunately that means the methods I described our out of date!

I have more complicated plans in the works, but for now I’m taking a few giant leaps into Node.js plugin development to see if it’s feasible for my master plans – and it not only looks feasible for a newcomer like me, but really easy in an unsettling way.

You make your first Node.js plugin and think to yourself: “Wow, that’s all it was?! Why was I scared of C++ for so long?”.  And then you sort of wondering if you just hit a big iceberg and you’re only seeing the tip.  Well, what if I am?

I present to you guys the tip of the iceberg.

First, one needs to realize that Node.js is built on Google’s V8 engine – the very same Javascript engine that runs in Chrome.  C++ (and NOT Javascript) is it’s native language.  What’s even odder to realize is that when you talk about making plugins for Node – I’m starting to think that I’m ALSO making plugins for Chrome or Chromium.  It’s just crazy to think about all that power you’re about to wield.

Also, Node.js is the PERFECT place to start.  I’d absolutely love to make awesome desktop applications in Chromium – with Adobe Brackets and Spotify being some pretty prominent examples of Chromium based applications.   But I can only imagine how much more complicated having to deal with a C++ application with a user interface is than just a plain old command line program.  Soo….I think Node.js will be pretty perfect here.

My reasons for attempting C++ in Node.js are basically the only reasons anyone ever introduces C++ into something else.

It’s fast.

I have a C++ library that I’d like to use and I’m not smart enough or don’t have the time to rewrite it.

Both of these reasons apply to what I’d like to do, but mostly the latter.  So given that, I shoved my C++ library aside and tried to figure out how to do the most trivial C++ module for Node.js.  It turns out that a lot of what’s on the internet is wrong depending on whether you’re running the latest version of Node (0.8) like I am.  Many articles you’ll find on the internet delve deep explaining how to use the WAF tool to compile C++ to Node.js.

Unfortunately, for the two hours I wasted trying to get it working, WAF is deprecated in Node!  Node-waf is a Node wrapper for the WAF build tool, but going forward we’ll be using GYP…or rather node-gyp.

 

Getting Set-Up

To get node-gyp up and running, install from NPM:

npm install -g node-gyp

Simple right?  Just like you’re installing any other node package.  Gyp reportedly depends on Python, Make, and a C++ compiler like GCC.  Doing this on Ubuntu, I don’t think I had to worry about these dependencies – as they were already on my system.

Assuming everything is set on your system – the best next step is to check out the official Node.js documentation.  I was a little surprised by this, but Node.js seems to have excellent documentation.  Officially, these modules/plugins are called “addons” and can be seen in the Addons section of Node’s documentation.

 

Building “Hello World”

Here’s the “Hello World” example copied right from the docs:

#include <node.h>
#include <v8.h>

using namespace v8;

Handle<Value> Method(const Arguments& args) {
  HandleScope scope;
  return scope.Close(String::New("world"));
}

void init(Handle<Object> target) {
  target->Set(String::NewSymbol("hello"),
      FunctionTemplate::New(Method)->GetFunction());
}
NODE_MODULE(hello, init)

Breaking this down looks daunting, but once you figure out the rhyme and reason, it’s not too shabby.  I think the includes at the top are fairly self explanatory – but lets start at the bottom.  Here we declare the NODE_MODULE.  It’s called “hello”, and it’s entry point is “init”.  So when we call it from node, the module is actually being named “hello” here, and it will run the “init” method right when it loads.

This example is a bit confusing, as the NewSymbol is also called “hello”.  Ignore this for now – first lets take a look at the “binding.gyp” file (the compiler build instructions):

{
  "targets": [
    {
      "target_name": "hello",
      "sources": [ "hello.cc" ]
    }
  ]
}

This target name “hello” has to match the NODE_MODULE declaration “hello”.  Basically, this “target” targets the NODE_MODULE name, and this NODE_MODULE needs to specify the main entry point of our little AddOn, which is the “init” function.  And lastly, we have to specify which file the target is in – and here it’s “hello.cc”.   It’s actually a matter of preference in C++ land whether you choose to call your file *.cc or *.cpp (I tried it, either works!)

So, fantastic! We’ve got ourselves a Node.js AddOn!  To compile run:

node-gyp configure build

…from your command line.  It’s actually two steps – configure prepares the various files that are needed to make the AddOn, while build actually does the compilation.  In the end, you’ll have a “hello.node” file in your build/release folder.

To actually use it in Node, just do the normal require, declare, and call:

var myaddon = require("./libs/build/Release/hello.node");
console.log( myaddon.hello() );

Breaking Down the Source

What we get out of this is your console printing: “world”.  How does it actually get here from the init method?  Well, this is where it gets a little hairy and abstract.  THIS is where you get punished for learning C++ from Node.js.  It all seems to be a weird glue between Javascript and C++.

Remember our init method:

void init(Handle<Object> target) {
  target->Set(String::NewSymbol("hello"),
      FunctionTemplate::New(Method)->GetFunction());
}

Here, we take the target, which is presumably the Node.js binding, and set a property on it – as if it were a dictionary or hash.  Our hash key is “hello”, and we use V8 to templatize and instantiate a new function that we’ve called “Method”.  There seems to be some V8/Node formality here, above and beyond C++ really – but THIS is how we’ve made our Node AddOn come to have the “hello()” method.

There’s a little more weird glue in the method itself:

Handle<Value> Method(const Arguments& args) {
  HandleScope scope;
  return scope.Close(String::New("world"));
}

I don’t know how the scope is created here – it looks like something from nothing to me – but it looks like just by declaring scope, we’ve successfully created our Javascript/C++ glue – so when we close our scope we return our string of “world”.  It’s still a little incomprehensible to me what’s actually happening here – but hey….we know how to return a value to JS!

 

Dealing with Parameters

Parameters also seem a bit weird.  I wasn’t able to explicitly say Method (int x, int y, etc), I think the parameters must come in as const Arguments& args….basically an array of arguments.  The documentation shows us how to deal with type checking them and converting them:

  if (args.Length() < 2) {
    ThrowException(Exception::TypeError(String::New("Wrong number of arguments")));
    return scope.Close(Undefined());
  }

  if (!args[0]->IsNumber() || !args[1]->IsNumber()) {
    ThrowException(Exception::TypeError(String::New("Wrong arguments")));
    return scope.Close(Undefined());
  }

  Local<Number> num = Number::New(args[0]->NumberValue() +
      args[1]->NumberValue());
  return scope.Close(num);
}

Pay attention here how you ALWAYS are doing conversion.  Whether IsNumber() or NumberValue(), you are basically extracting a value from a memory reference.  This isn’t Javascript anymore, where it will just type convert for you….this isn’t even Java where it will just take your memory reference as a value.  You need to RECOGNIZE that these are memory references, and you need to extract and convert explicitly to even get the integer value!  And then to even get this number back to Javascript, you are throwing it into the Local<Number> space.  I assume that this puts it in the context of the V8 Javascript engine – going from that separate world of C++ over to Node.

 

My Example

That’s pretty much as far as I got, but I did create a more complicated example.  Basically, my end goal here is to get x,y,z (3D) coordinates from C++ and pass to node.  Since I don’t have my fancy C++ library in place yet – I just make my AddOn generate random numbers and put them into a native JSON object and pass them on to Node.

Here’s a gist of my “randomcoords.node” AddOn

After I build it, I can use it like so:

var randCoords = require("./libs/build/Release/randomcoords.node");
var cursor = randCoords.getRandomCoords3D(600, 400, 100); // params are max values for random output
console.log('{ "x":' + cursor.x +  ', "y":' + cursor.y + ', "z":' + cursor.z + '}');

But of course – I don’t log it, I send it on via a websocket to my browser to update the position of a sprite, but that’s something for another day!

 

Go, and create your unholy monster!

Hope that all explained things – I know I can’t explain everything, but I feel like I know just enough to be dangerous, and I hope that you can be dangerous too!  I think this opens up a lot of power.  I’m quite confident that you can do similar things in Python, Ruby, or whatever – but we’re messing with the V8 engine here, and this can hopefully be knowledge transferred to Chromium someday so we can build the next Adobe Brackets or Spotify…it’s quite exciting!  My ultimate goal here is to use the OpenNI project within Node and transfer natural user interface data over to the browser via websockets.  So far so good!

32 thoughts on “C++ and Node.js: An Unholy Combination….But Oh So Right”

  1. I have always been a C++ fan for it’s speed, and perhaps because it’s the language that I’m most experienced with.

    It was when I started learning Node.js when I came across the fact that we can actually develop plugins for it in C++.
    Ever since then I have wondered how to do this, but never dared to look into the documentation.
    Thanks for the great article. It’s going to be really helpful for me when I start working on my next project.

  2. Great intro.

    I assume I need some type of websocket to display data from a C++ lib onto a website via node…do you have any suggestion as to which one is best?

    1. Sure. Actually I’m using Node.js these days in combination with webkit provided by Atom-Shell or Node-Webkit, so I avoid the browser altogether in those situations. However, if you want to target the browser, websockets are a good way to go. Lots of people love Socket.io, and I’m sure it’s great, but I prefer going a bit simpler. You can check out my Github repo to see how I made a C++ Node add on and stream the data out via websockets.

      Here’s the server-side: https://github.com/bengfarrell/nuimotion/blob/master/quickstart/websocketquickstart.js
      And here’s the client-side: https://github.com/bengfarrell/nuimotion/blob/master/quickstart/nuimotion-sockets.js

      1. Socket.io looks good and I also had a look at the quickstart section of nuimotion. As a C++ programmer though I feel a little out of my depth and usually rely on simple examples in order to get me started.

        How would I use the C++ hello world example here to display the contents inside a index.html file instead of on the console? Is it possible to have the string ‘world’ be displayed in a html tag if so do you have an example I can look at?

        1. Dear Imran,

          I offer you this wisdom:

          “Not I, nor anyone else can travel that road for you.
          You must travel it by yourself.
          It is not far. It is within reach.
          Perhaps you have been on it since you were born, and did not know.
          Perhaps it is everywhere – on water and land.”
          ― Walt Whitman, Leaves of Grass

          To begin on this road I suggest reading about the HTML DOM:
          http://www.w3schools.com/js/js_htmldom.asp

          And also jQuery DOM manipulation:
          http://learn.jquery.com/using-jquery-core/manipulating-elements/

          May the force be with you,
          Eric

          1. What Eric is getting at is web development is a big topic. You’ll probably find tons of resources for tying Javascript to the DOM online. If you look up at jquery, that might be the perfect place to start. Lots of newcomers use jQuery pretty handily as their first entry point into web dev. http://jquery.com/.

  3. Great article. B.t.w, there is an other great way to use C++ with Node.
    Rather than writing a module, write a worker-client. This also has amazing scalability potential. If for the client you make use of boost::asio, things become conceptually a very good fit as asynchonous events propogate perfectly between frameworks.

    1. Hi Rob,

      Do you mean to write a separate application in C++ (using boost asio) and communicate with the node through the socket?

  4. Great instructions.

    I just wanted to check if it’s possible to also create a “process” in C++ (compiled with node-gyp and started from node.js).
    For instance if I have some c-application I want to compile with node-gyp (which I create a wrapper around to be accessible from node.,js).
    This wrapper might include init function, plus some other functions I want to use to do stuff with the “c-application” (all function calls are muxed via the wrapper function).
    When I call the init function, it should initialize all variables etc.
    If I call the “function” again, will I be in the same context of will all variable settings be gone?

    Thanks,
    Niklas

    1. I haven’t done that much yet with this stuff. I will say that you’re right – the code will start, finish executing, and then go away. So, variables/state are not maintained (AFAIK).

      I have, however, had to do some intensive processing in the background on incoming data that’s coming in for the life of the Node.js application. In this case, I kept a background thread alive and processing the application, which also kept the rest of the Node addon alive and sending data.

      A background thread might be a little much for doing what you want – perhaps it would be better to save state in a file or something. Also perhaps, there’s another way that I’m not familiar with.

  5. Excellent article. Interesting. I am relatively new to web development.

    Btw regarding this:

    HandleScope scope;

    It is not something for nothing. HandleScope is a class probably defined in the v8 namespace. The scope variable is an instantiation of that class. Basically the default constructor for HandleScope is being called. The scope object goes out of scope when the function exits.

    1. Yup I’m sure you’re right, its just a little awkward looking for me not dealing with C++ all the time. Declaring a variable like that, I’d expect it to be null until I use it or instantiate it. But I’m sure it’s just a singleton class and things like this are syntactically slightly different in other languages

  6. Hi,
    Can I use a node USB module in client side js.?
    I am not able to browserify USB module and use in client side script, maybe because its a addon.

    1. Not sure which USB module you mean, but the browser won’t deal with most USB devices directly. Things like game controllers and MIDI are some cool things that the browser does support these days and those tend to go through USB, but as far as I know, working with just any USB device isn’t supported.

  7. When I save this file as hello.cc, open terminal related to node and write node-gyp configure build
    it shows the following error-
    SyntaxError: Unexpected identifier
    at Object.exports.createScript (vm.js:44:10)
    at REPLServer.defaultEval (repl.js:117:23)
    at bound (domain.js:254:14)
    at REPLServer.runBound [as eval] (domain.js:267:12)
    at REPLServer. (repl.js:279:12)
    at REPLServer.emit (events.js:107:17)
    at REPLServer.Interface._onLine (readline.js:214:10)
    at REPLServer.Interface._line (readline.js:553:8)
    at REPLServer.Interface._ttyWrite (readline.js:830:14)
    at ReadStream.onkeypress (readline.js:109:10)
    >

    Please help !

    1. Thanks, that’s correct – starting in 0.11, the API changed a bit, and its common practice to use NAN (from NPM) to handle the abstractions

  8. As you mentioned, NAN is very helpful, but I also wanted to point out the ffi package (formerly node-ffi), which is great for loading dynamic libraries. If you have the option to use dynamic libraries then this is perfect since it so much easier to interface with.

    Great article!

  9. Excellent (and currently highly Google-ranked) article. One thing that should be mentioned is to at least consider the alternative of spawning any C++ code as a separate process and using node’s efficient asynchronous I/O to communicate with the code over standard OS streams. The benefits include being able to trivially take advantage of multicore processors (because the C++ code now runs in its own process), and being insulated from crashes in the C++ code. Of course, your node addon could fork itself, but then all you’re really gaining with this approach is the cross-platform compilation of node-gyp.

  10. Hi, I tried your example on Windows8.1 x64 with Node 4.1.1 and Python 2.7.
    I got a bunch of errors which I do not understand (I am a very poor C++ programmer):


    C:\data\tryout\nodeCpp>node-gyp configure build
    gyp info it worked if it ends with ok
    gyp info using node-gyp@3.3.1
    gyp info using node@4.1.1 | win32 | x64
    gyp info spawn C:\data\tools\python27\python.exe
    gyp info spawn args [ 'C:\\Users\\mvrm\\AppData\\Roaming\\npm\\node_modules\\node-gyp\\gyp\\gyp_main.py',
    gyp info spawn args 'binding.gyp',
    gyp info spawn args '-f',
    gyp info spawn args 'msvs',
    gyp info spawn args '-G',
    gyp info spawn args 'msvs_version=auto',
    gyp info spawn args '-I',
    gyp info spawn args 'C:\\data\\tryout\\nodeCpp\\build\\config.gypi',
    gyp info spawn args '-I',
    gyp info spawn args 'C:\\Users\\mvrm\\AppData\\Roaming\\npm\\node_modules\\node-gyp\\addon.gypi',
    gyp info spawn args '-I',
    gyp info spawn args 'c:\\data\\home\\.node-gyp\\4.1.1\\include\\node\\common.gypi',
    gyp info spawn args '-Dlibrary=shared_library',
    gyp info spawn args '-Dvisibility=default',
    gyp info spawn args '-Dnode_root_dir=c:\\data\\home\\.node-gyp\\4.1.1',
    gyp info spawn args '-Dnode_gyp_dir=C:\\Users\\mvrm\\AppData\\Roaming\\npm\\node_modules\\node-gyp',
    gyp info spawn args '-Dnode_lib_file=node.lib',
    gyp info spawn args '-Dmodule_root_dir=C:\\data\\tryout\\nodeCpp',
    gyp info spawn args '--depth=.',
    gyp info spawn args '--no-parallel',
    gyp info spawn args '--generator-output',
    gyp info spawn args 'C:\\data\\tryout\\nodeCpp\\build',
    gyp info spawn args '-Goutput_dir=.' ]
    gyp info spawn C:\Program Files (x86)\MSBuild\14.0\bin\msbuild.exe
    gyp info spawn args [ 'build/binding.sln',
    gyp info spawn args '/clp:Verbosity=minimal',
    gyp info spawn args '/nologo',
    gyp info spawn args '/p:Configuration=Release;Platform=x64' ]
    Building the projects in this solution one at a time. To enable parallel build, please add the "/m" switch.
    hello.cc
    ..\hello.cc(6): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int [C:\data\tryout\nodeCpp\build\hello.vcxproj]
    ..\hello.cc(6): error C2143: syntax error: missing ',' before '&' [C:\data\tryout\nodeCpp\build\hello.vcxproj]
    ..\hello.cc(7): error C2248: 'v8::HandleScope::HandleScope': cannot access protected member declared in class 'v8::HandleScope' [C:\data\tryout\nodeCpp\build\hello.vcxproj]
    c:\data\home\.node-gyp\4.1.1\include\node\v8.h(885): note: see declaration of 'v8::HandleScope::HandleScope'
    c:\data\home\.node-gyp\4.1.1\include\node\v8.h(869): note: see declaration of 'v8::HandleScope'
    ..\hello.cc(8): error C2039: 'Close': is not a member of 'v8::HandleScope' [C:\data\tryout\nodeCpp\build\hello.vcxproj]
    c:\data\home\.node-gyp\4.1.1\include\node\v8.h(869): note: see declaration of 'v8::HandleScope'
    ..\hello.cc(8): error C2039: 'New': is not a member of 'v8::String' [C:\data\tryout\nodeCpp\build\hello.vcxproj]
    c:\data\home\.node-gyp\4.1.1\include\node\v8.h(2081): note: see declaration of 'v8::String'
    ..\hello.cc(8): error C3861: 'New': identifier not found [C:\data\tryout\nodeCpp\build\hello.vcxproj]
    ..\hello.cc(12): error C2039: 'NewSymbol': is not a member of 'v8::String' [C:\data\tryout\nodeCpp\build\hello.vcxproj]
    c:\data\home\.node-gyp\4.1.1\include\node\v8.h(2081): note: see declaration of 'v8::String'
    ..\hello.cc(12): error C3861: 'NewSymbol': identifier not found [C:\data\tryout\nodeCpp\build\hello.vcxproj]
    ..\hello.cc(13): error C2664: 'v8::Local v8::FunctionTemplate::New(v8::Isolate *,v8::FunctionCallback,v8::Local,v8::Local,int)': cannot convert argumen
    t 1 from 'v8::Local (__cdecl *)(const int)' to 'v8::Isolate *' [C:\data\tryout\nodeCpp\build\hello.vcxproj]
    ..\hello.cc(13): note: There is no context in which this conversion is possible
    ..\hello.cc(13): error C2227: left of '->GetFunction' must point to class/struct/union/generic type [C:\data\tryout\nodeCpp\build\hello.vcxproj]
    gyp ERR! build error
    gyp ERR! stack Error: `C:\Program Files (x86)\MSBuild\14.0\bin\msbuild.exe` failed with exit code: 1
    gyp ERR! stack at ChildProcess.onExit (C:\Users\mvrm\AppData\Roaming\npm\node_modules\node-gyp\lib\build.js:276:23)
    gyp ERR! stack at emitTwo (events.js:87:13)
    gyp ERR! stack at ChildProcess.emit (events.js:172:7)
    gyp ERR! stack at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
    gyp ERR! System Windows_NT 6.3.9600
    gyp ERR! command "C:\\Program Files\\nodejs\\node.exe" "C:\\Users\\mvrm\\AppData\\Roaming\\npm\\node_modules\\node-gyp\\bin\\node-gyp.js" "configure" "build"
    gyp ERR! cwd C:\data\tryout\nodeCpp
    gyp ERR! node -v v4.1.1
    gyp ERR! node-gyp -v v3.3.1
    gyp ERR! not ok

    Any assistance is welcome!

    Michiel

    1. Sorry, but I’m afraid this information is fairly out of date at this point. I believe I was writing this when 0.8 was new and I haven’t had a chance to go back and learn the new ways. As of 0.11, you’d use a module called NAN to abstract the differences, but even that may be outdated by now (not sure)

  11. I get several compiler errors I assume due to node version running:

    macbookproloreto:native admin$ node -v
    v4.2.6
    macbookproloreto:native admin$ node-gyp -v
    v3.3.1

    whit errors:

    CXX(target) Release/obj.target/hello/hello.o
    ../hello.cc:6:28: error: unknown type name ‘Arguments’; did you mean ‘v8::internal::Arguments’?
    Handle Method(const Arguments& args) {
    ^~~~~~~~~
    v8::internal::Arguments
    /Users/admin/.node-gyp/4.2.6/include/node/v8.h:139:7: note: ‘v8::internal::Arguments’ declared here
    class Arguments;
    ^
    ../hello.cc:7:15: error: calling a protected constructor of class ‘v8::HandleScope’
    HandleScope scope;
    ^
    /Users/admin/.node-gyp/4.2.6/include/node/v8.h:885:13: note: declared protected here
    V8_INLINE HandleScope() {}
    ^
    ../hello.cc:8:16: error: no member named ‘Close’ in ‘v8::HandleScope’
    return scope.Close(String::New(“world”));
    ~~~~~ ^
    ../hello.cc:8:30: error: no member named ‘New’ in ‘v8::String’
    return scope.Close(String::New(“world”));
    ~~~~~~~~^
    ../hello.cc:13:29: error: cannot initialize a parameter of type ‘v8::Isolate *’ with an lvalue of type ‘Handle (const v8::internal::Arguments &)’
    FunctionTemplate::New(Method)->GetFunction());
    ^~~~~~
    /Users/admin/.node-gyp/4.2.6/include/node/v8.h:4350:16: note: passing argument to parameter ‘isolate’ here
    Isolate* isolate, FunctionCallback callback = 0,
    ^
    ../hello.cc:12:23: error: no member named ‘NewSymbol’ in ‘v8::String’
    target->Set(String::NewSymbol(“hello”),
    ~~~~~~~~^
    In file included from ../hello.cc:1:
    In file included from /Users/admin/.node-gyp/4.2.6/include/node/node.h:42:
    /Users/admin/.node-gyp/4.2.6/include/node/v8.h:327:9: error: cannot initialize a member subobject of type ‘v8::FunctionTemplate *’ with an lvalue of type ‘const char *’
    : val_(that) {}
    ^ ~~~~
    ../hello.cc:8:34: note: in instantiation of function template specialization ‘v8::Local::Local’ requested here
    return scope.Close(String::New(“world”));
    ^
    7 errors generated.
    make: *** [Release/obj.target/hello/hello.o] Error 1
    gyp ERR! build error
    gyp ERR! stack Error: `make` failed with exit code: 2
    gyp ERR! stack at ChildProcess.onExit (/usr/local/lib/node_modules/node-gyp/lib/build.js:276:23)
    gyp ERR! stack at emitTwo (events.js:87:13)
    gyp ERR! stack at ChildProcess.emit (events.js:172:7)
    gyp ERR! stack at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
    gyp ERR! System Darwin 14.5.0
    gyp ERR! command “/usr/local/bin/node” “/usr/local/bin/node-gyp” “configure” “build”
    gyp ERR! cwd /Users/admin/Projects/MusiXmatch/musixmatch-node-sdk/lib/tests/native
    gyp ERR! node -v v4.2.6
    gyp ERR! node-gyp -v v3.3.1
    gyp ERR! not ok

    1. Yah, you’re the second person to call this out on this older article. I haven’t kept up with C++ in Node since this time. It would work if you were running v0.8. I’m gonna add a disclaimer to the top. Thanks!

  12. Hi, your tutorial is really interesting and well made.
    But trying to compile with “node-gyp configure build”, I get a lot of errors.

    root@vlz2-billsrv01:/Sources/node/test# node-gyp configure build
    gyp info it worked if it ends with ok
    gyp info using node-gyp@3.4.0
    gyp info using node@4.6.0 | linux | x64
    gyp info spawn /usr/bin/python2
    gyp info spawn args [ ‘/usr/local/node/lib/node_modules/node-gyp/gyp/gyp_main.py’,
    gyp info spawn args ‘binding.gyp’,
    gyp info spawn args ‘-f’,
    gyp info spawn args ‘make’,
    gyp info spawn args ‘-I’,
    gyp info spawn args ‘/Sources/node/test/build/config.gypi’,
    gyp info spawn args ‘-I’,
    gyp info spawn args ‘/usr/local/node/lib/node_modules/node-gyp/addon.gypi’,
    gyp info spawn args ‘-I’,
    gyp info spawn args ‘/root/.node-gyp/4.6.0/include/node/common.gypi’,
    gyp info spawn args ‘-Dlibrary=shared_library’,
    gyp info spawn args ‘-Dvisibility=default’,
    gyp info spawn args ‘-Dnode_root_dir=/root/.node-gyp/4.6.0’,
    gyp info spawn args ‘-Dnode_gyp_dir=/usr/local/node/lib/node_modules/node-gyp’,
    gyp info spawn args ‘-Dnode_lib_file=node.lib’,
    gyp info spawn args ‘-Dmodule_root_dir=/Sources/node/test’,
    gyp info spawn args ‘–depth=.’,
    gyp info spawn args ‘–no-parallel’,
    gyp info spawn args ‘–generator-output’,
    gyp info spawn args ‘build’,
    gyp info spawn args ‘-Goutput_dir=.’ ]
    gyp info spawn make
    gyp info spawn args [ ‘BUILDTYPE=Release’, ‘-C’, ‘build’ ]
    make: Entering directory `/Sources/node/test/build’
    CXX(target) Release/obj.target/hello/hello.o
    ../hello.cc:6:28: error: ‘Arguments’ does not name a type
    ../hello.cc:6:39: error: ISO C++ forbids declaration of ‘args’ with no type [-fpermissive]
    In file included from /root/.node-gyp/4.6.0/include/node/node.h:42:0,
    from ../hello.cc:1:
    /root/.node-gyp/4.6.0/include/node/v8.h: In function ‘v8::Handle Method(const int&)’:
    /root/.node-gyp/4.6.0/include/node/v8.h:885:13: error: ‘v8::HandleScope::HandleScope()’ is protected
    ../hello.cc:7:16: error: within this context
    ../hello.cc:8:19: error: ‘class v8::HandleScope’ has no member named ‘Close’
    ../hello.cc:8:25: error: ‘New’ is not a member of ‘v8::String’
    ../hello.cc: In function ‘void init(v8::Handle)’:
    ../hello.cc:12:16: error: ‘NewSymbol’ is not a member of ‘v8::String’
    ../hello.cc:13:38: error: no matching function for call to ‘v8::FunctionTemplate::New(v8::Handle (&)(const int&))’
    ../hello.cc:13:38: note: candidate is:
    In file included from /root/.node-gyp/4.6.0/include/node/node.h:42:0,
    from ../hello.cc:1:
    /root/.node-gyp/4.6.0/include/node/v8.h:4349:34: note: static v8::Local v8::FunctionTemplate::New(v8::Isolate*, v8::FunctionCallback, v8::Local, v8::Local, int)
    /root/.node-gyp/4.6.0/include/node/v8.h:4349:34: note: no known conversion for argument 1 from ‘v8::Handle(const int&) {aka v8::Local(const int&)}’ to ‘v8::Isolate*’
    ../hello.cc: In function ‘v8::Handle Method(const int&)’:
    ../hello.cc:9:1: warning: control reaches end of non-void function [-Wreturn-type]
    make: *** [Release/obj.target/hello/hello.o] Error 1
    make: Leaving directory `/Sources/node/test/build’
    gyp ERR! build error
    gyp ERR! stack Error: `make` failed with exit code: 2
    gyp ERR! stack at ChildProcess.onExit (/usr/local/node/lib/node_modules/node-gyp/lib/build.js:276:23)
    gyp ERR! stack at emitTwo (events.js:87:13)
    gyp ERR! stack at ChildProcess.emit (events.js:172:7)
    gyp ERR! stack at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
    gyp ERR! System Linux 3.2.0-67-generic
    gyp ERR! command “/usr/local/node/bin/node” “/usr/local/node/bin/node-gyp” “configure” “build”
    gyp ERR! cwd /Sources/node/test
    gyp ERR! node -v v4.6.0
    gyp ERR! node-gyp -v v3.4.0
    gyp ERR! not ok

    Could you tell me what I have missed ?

    Regards

    1. Thanks for the compliment! You did miss one thing…unfortunately, you’ll still be a bit disappointed. There’s a disclaimer I wrote back in May about this article because I was getting a few comments like yours on how it didn’t compile. The reason is that the article is pretty old, and was written for Node v0.8. The current version is 6.8. Lots of things have changed since, and I haven’t kept up with the C++/Node bridge to know how to update things. Sorry!

  13. Hey Ben, great article. However, I couldn’t find a single word “debug”, neither in the article itself, nor in the comments. How was your experience with debugging a C++ node addon? Thanks.

    1. It’s been awhile, but from what I remember, I was really just poking around and fixing compiler errors as they came up. I never enabled proper debugging in this, and don’t have much experience debugging with C++ in general.

Leave a Reply

Your email address will not be published. Required fields are marked *