Creating Node Addons

C/C++ extensions for fun and profit*

Marco Rogers

@polotek (twitter, github, irc, etc.)

*Typical results do not include fun or profit

Who am I?

What's an Addon?

Why would you wanna do this?


C library for encrypting data with blowfish.

    char* bcrypt_gensalt(u_int8_t log_rounds);
    char* bcrypt(const char* password, const char* salt);

Let's write an addon!

Code samples here (forthcoming)

    // our API
    var BCrypt = require('bcrypt').BCrypt;

    var salt = '$2a$12$L/QwZlqLTII.Qx/p9kLt5.';
    var encrypter = new BCrypt();
    console.log( encrypter.encrypt('passw0rd', salt) );

How does it work?

v8 API

    // js
    function encrypt() {
        this; // could be anything

        var arg1 = "loser";
        if(arguments.length == 1)

        return "Hello, " + arg1;

v8 API

    // C++
    Handle<Value> BCrypt::Encrypt(const Arguments& args) {
        args.This(); // of type Handle<Value>

        Handle<String> args1;
        if(args.Length() == 1) {
            args1 = args[0]->ToString();
        } else {
            args1 = String::New("loser");

        return String::Concat( String::New("Hello, "), args1 );

v8: Handles

Each reference to a js value in C/C++ is through a Handle. You need to "unwrap" Handles to get at the data types inside them.

A HandleScope is a temporary construct that keeps track of Handles and cleans them up when the stack pops off.

Always use a HandleScope at the beginning of your function.

v8: Handles

Local Handle - Cleaned up by scope after the function exits. Default handle type.

Persistent Handle - These allow you to keep objects around for as long as you need them.

v8: Handles

Probably the most important gotcha. Close the scope whenever you return a Handle from a function. Otherwise, the HandleScope will take it right out from under you.

    +HandleScope scope;

    return v8::Array::New();
    +return scope.Close(v8::Array::New());

Remember even innocent looking "literals" are actually Handles! Lots of commits that look like this.

node: ObjectWrap

        class BCrypt : public node::ObjectWrap {

          Handle<Value> BCrypt::Encrypt(const Arguments& args) {
            HandleScope scope;

            // retrieve your object from "this".
            BCrypt *bcrypt_obj = ObjectWrap::Unwrap<BCrypt>(args.This());

node: Classes and Utilities

        // C/C++
        class Connection : public node::EventEmitter {
          v8::Handle<v8::String> close = NODE_PSYMBOL("close");
          Emit(close_symbol, 0, NULL);
        // js
        var conn = new Connection();
        conn.on('close', function() { ... });

node: Classes and Utilities

Check out node/src/node.h for some nice macros and helper functions.

node: How to go from sync to async?

Kind of punting on this even though it's an important topic.

Node uses libeio to turn blocking file operations into non-blocking ones. It also has an API for doing this with any custom call. Push blocking library calls to a background thread. Isaac Schlueter has provided a simple example, node-async-simple. Complete but not comprehensive. Find out how you need to adapt this to your use case.

Don't try to access v8 from another thread. Unwrap everything to C/C++ types and only deal with those.

Lots we're not covering

Building with Waf

This process isn't fun. So...

Building with Waf

Just find a good one and learn from that. #winning

* libxmljs uses scons. Similar idea, another dependency. Not worth it.

Building with Waf

    # wscript
    srcdir = "."
    blddir = "build"

    def set_options(opt):

    def configure(conf):

    def build(bld):
        bcryptnode = bld.new_task_gen("cxx", "shlib", "node_addon") = "bcrypt_lib"
        bcryptnode.source = "src/ src/ src/"



        $> node --expose_gc addon_test.js

        // addon_test.js
        var libxmljs = require('libxmljs');
        var doc = libxmljs.parseXmlString('<pass><test/></pass>');
        console.log(doc.root().name()); // "pass" yay!
        // force GC, I hope nothing bad happened
        console.log(doc.root().name()); // Segfaults, destruction and death


Use tools to ensure quality

Someone write some blog posts about these


    $> npm help scripts

    // package.json
      "name": "bcrypt",
      "scripts": {
        "install": "node-waf configure build",
        "test": "node-waf configure build && nodeunit test/"


Is using make more future-proof or just another dependency?

    // package.json
      "name": "libxmljs",
      "scripts" :
      { "preinstall" : "make node",
        "test" : "make test"
    # MakeFile
            node-waf configure build

Should you distribute the lib with your addon?