Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
496 lines (337 sloc) 7.86 KB

Build the C link

Nikhil Marathe

Introduction

  • V8 is a powerful, fast JavaScript engine

  • It is self contained and easy to embed

    JS is the new Lua?

  • node.js is a thin wrapper around V8 and evented I/O (libuv)

Follow along

Slides and code

git clone git://github.com/nikhilm/jsfoo-pune-2012.git

We want to

Use C/C++ libraries in node.js

Exchange data between C++ ⇔ JS

Do asynchronous I/O

Getting started

Build

Run

$ node-waf configure build
...
'build' finished successfully (0.327s)

$ node
> require('./build/Release/firststep')
{}

Architecture

images/architecture.png

[1]you will need http://bespin.cz/~ondras/html/index.html

Handles

  • Think of them as smart pointers, GCed by V8

  • Also encode scope (Use HandleScope to manage handles)

  • Local - GCed as they go out of scope:

    Local<String> name; // also Handle<...>
    
  • Persistent - Must be manually disposed:

    Persistent<String> globalVariable;
    

Injecting primitives

Simple functions

exports.square = function(n) {
    return n * n;
}

We want to do this in C++

Simple functions

Registering with V8:

Simple functions

Implementation:

explain scope.Close

Templates

FunctionTemplate                            ???

FunctionTemplate::GetFunction               square [Function]

FunctionTemplate::InstanceTemplate()        What `this` would be in 'new square()'

FunctionTemplate::PrototypeTemplate()       square.prototype

Simple objects

exports.Inventory = function() {
    this.items = 257;
}

// later
var iv = new Inventory();
console.log(iv.items);

This is the classic object oriented JS style

Simple objects

Methods

Inventory.prototype.addStock = function(newStock) {
    this.items += newStock;
}

Inventory.prototype.ship = function(orders) {
    if (this.items < orders)
        throw Exception("Not enough items");

    this.items -= orders
}

Methods

Registering prototype methods

Methods

Accessing object properties

Methods

Throwing an exception

ObjectWrap

  • Associate native C++ objects with JS objects
  • Node specific class which manages garbage collection
  • Stored internally in fields

images/internal.png

ObjectWrap

// native C++ class
namespace Library {
class Inventory {
    Inventory();
    void addStock(int);
    int ship(int);
    int getItems();

    int items; // private
};
}

ObjectWrap

Setting internal field count

ObjectWrap

Wrapping

ObjectWrap

Unwrapping

Going Async

  • The easiest way is to use uv_queue_work()

  • Every async call requires a set of 3 functions
    1. Set up and invoke uv_queue_work()
    2. Do blocking task (run in separate thread)
    3. Clean up (run in main thread)
  • Use a 'baton' to pass around data
    • uv_request_t is used by libuv
    • But it's data field is important to store the baton itself
  • Slightly cumbersome :(

Going Async

Going Async

The native blocking code (method of class Library::Inventory)

Going Async

The baton

Going Async

JS callback

Going Async

Thread pool function

Going Async

Clean up

Going Async

Output

After reshelve in source
Tick
Tick
Tick
Tick
Reshelving done

Linking your library

Linking external libs in Waf:

def configure(conf):
  # ...
  # uses pkg-config
  conf.check_cfg(package='<pkg-config name>', args='--cflags --libs',
  uselib_store='ALIAS')

def build(bld):
  # ...
  obj.uselib = 'ALIAS'

Holder vs This

  • args.This() is always the this object passed in to the function
  • args.Holder() runs up the prototype chain to the 'right' object
  • Signatures decide the 'right' object, automatically handled by NODE_PROTOTYPE_SET_METHOD
  • Always use Holder() to be on the safe side

Things I haven't covered

  • Accessors
    • Per property accessors
    • Indexed accessors ( object[5] )
    • Named property accessors ( object.property )
  • Function Signatures and HasInstance for type safety

  • Emitting events using new JS only EventEmitter

  • Details of libuv

  • Using V8 on its own

You might want to look at

End notes

Contact:

Cover image by Munjal Savla (by-nc-sa)

Extra material below

Calling JS functions

Calling JS functions

Strings to-and-fro

v8::String -> C string

Strings to-and-fro

C string -> v8::String