SlideShare a Scribd company logo
1 of 45
Download to read offline
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

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

using namespace v8;

extern "C" {
    static void Init(Handle<Object> target) {
    }
    NODE_MODULE(firststep, Init)
}
Build

# firststep/wscript
import Options

def set_options(opt):
    opt.tool_options("compiler_cxx")

def configure(conf):
    conf.check_tool("compiler_cxx")
    conf.check_tool("node_addon")

def build(bld):
    obj = bld.new_task_gen("cxx", "shlib", "node_addon")
    obj.target = "firststep"
    obj.source = "firststep.cc"
Run

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

$ node

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




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
#include <math.h>
#include <v8.h>
#include <node.h>
#include <node_version.h>
using namespace v8;

extern "C" {
    static void Init(Handle<Object> target) {
        target->Set(String::NewSymbol("pi"),
                    Number::New(M_PI));

        NODE_DEFINE_CONSTANT(target, NODE_MINOR_VERSION);

        target->Set(String::New("name"), String::New("Nikhil"));
    }
    NODE_MODULE(primitives, Init)
}
Simple functions




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

We want to do this in C++
Simple functions
Registering with V8:

 Handle<Value> Square(const Arguments &args)

 static void Init(Handle<Object> target) {
         HandleScope scope;

          Handle<FunctionTemplate> squareTpl =
              FunctionTemplate::New(Square);

          target->Set(String::New("square"),
                      squareTpl->GetFunction());
     }
Simple functions
Implementation:

 Handle<Value> Square(const Arguments &args) {
     HandleScope scope;

     int a = args[0]->Int32Value();
     int sq = a * a;

     return scope.Close(Integer::New(sq));
 }

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
static void Init(Handle<Object> target) {
        HandleScope scope;

        Handle<FunctionTemplate> inventoryTpl =
            FunctionTemplate::New(Inventory);

        Handle<ObjectTemplate> instance =
            inventoryTpl->InstanceTemplate();

        instance->Set(String::New("items"), Integer::New(257));

        target->Set(String::NewSymbol("Inventory"),
                    inventoryTpl->GetFunction());
    }


Handle<Value> Inventory(const Arguments &args) {
    return args.This();
}
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

 // operating on inventoryTpl->PrototypeTemplate()
         NODE_SET_PROTOTYPE_METHOD(inventoryTpl,
                                   "addStock",
                                   AddStock);
         NODE_SET_PROTOTYPE_METHOD(inventoryTpl,
                                   "ship",
                                   Ship);

         target->Set(String::NewSymbol("Inventory"),
                     inventoryTpl->GetFunction());
Methods
Accessing object properties
Handle<Value> AddStock(const Arguments &args) {
    HandleScope scope;

    Handle<Object> This = args.This();

    int items = This->Get(String::New("items"))->Uint32Value();

    items += args[0]->Uint32Value();

    This->Set(String::New("items"), Integer::New(items));

    return Undefined();
}
Methods
Throwing an exception
Handle<Value> Ship(const Arguments &args) {
    HandleScope scope;

    Handle<Object> This = args.This();
    int items = This->Get(String::New("items"))->Uint32Value();

    int orders = args[0]->Uint32Value();

    if (items < orders)
        return ThrowException(String::New("Not enough items"));

    This->Set(String::New("items"), Integer::New(items - orders));

    return Undefined();
}
ObjectWrap

 • Associate native C++ objects with JS objects
 • Node specific class which manages garbage collection
 • Stored internally in fields
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

 Handle<ObjectTemplate> instance =
             inventoryTpl->InstanceTemplate();

          instance->SetInternalFieldCount(1);
ObjectWrap
Wrapping

namespace binding {
class Inventory : public ObjectWrap {
public:
    static Handle<Value> New(const Arguments &args) {
        Inventory *wrapper = new Inventory();
        wrapper->Wrap(args.Holder());
        return args.Holder();
    }
ObjectWrap
Unwrapping
static Handle<Value> Ship(const Arguments &args) {
        // extract
        Inventory *wrapper = Unwrap<Inventory>(args.Holder());

        int orders = args[0]->Uint32Value();
        int result = wrapper->inv->ship(orders);

        if (result == -1)
            return ThrowException(String::New("Not enough items"));

        return Undefined();
    }
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
var inv = new (require('./build/Release/async')).Inventory()

inv.reshelve(function() {
    console.log("Reshelving done");
})
console.log("After reshelve in source");
for (var i = 1; i < 5; i++)
    setTimeout(function() {
        console.log("Tick");
    }, i*1000);
Going Async
The native blocking code (method of class Library::Inventory)

 void reshelve() {
         sleep(5);
     }
Going Async
The baton
struct ReshelveBaton {
    uv_work_t request;
    Persistent<Function> callback;
    Inventory *wrapper;
    // any other data that has to be sent to the callback
    // or for async processing.
}
Going Async
JS callback
static Handle<Value> Reshelve(const Arguments &args) {
        Inventory *wrapper = Unwrap<Inventory>(args.Holder());

        Handle<Function> cb = Handle<Function>::Cast(args[0]);

        ReshelveBaton *baton = new ReshelveBaton();
        baton->request.data = baton;
        baton->callback = Persistent<Function>::New(cb);
        baton->wrapper = wrapper;

        uv_queue_work(Loop(), &baton->request,
                      ReshelveAsync, ReshelveAsyncAfter);

        return Undefined();
    }
Going Async
Thread pool function

 static void ReshelveAsync(uv_work_t *req) {
         // This runs in a separate thread
         // NO V8 interaction should be done
         ReshelveBaton *baton =
             static_cast<ReshelveBaton*>(req->data);
         // if you want to modify baton values
         // do synchronous work here
         baton->wrapper->inv->reshelve();
     }
Going Async
Clean up
static void ReshelveAsyncAfter(uv_work_t *req) {
        ReshelveBaton *baton =
            static_cast<ReshelveBaton*>(req->data);

           Handle<Value> argv[] = { Null() }; // no error
           baton->callback->Call(Context::GetCurrent()->Global(),
                                 1, argv);

           baton->callback.Dispose();
           delete baton;
    }
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

 • https://github.com/weaver/uuidjs
 • https://github.com/nikhilm/node-taglib
 • https://github.com/pietern/hiredis-node
End notes
Contact:
  • @nikhilcutshort
  • nsm.nikhil@gmail.com



Cover image by Munjal Savla (by-nc-sa)
Extra material below
Calling JS functions

var calljs = require("./build/Release/calljs")

var f = function() {
    console.log("This", this);
    console.log(arguments);
}

calljs.apply(f, { cool: "dude" }, "one", 2, 3.14);
Calling JS functions
Handle<Value> Apply(const Arguments &args) {
    HandleScope scope;

    Handle<Function> func = Handle<Function>::Cast(args[0]);
    Handle<Object> receiver = args[1]->ToObject();

    Handle<Value> *argv = new Handle<Value>[args.Length() - 2];
    for (int i = 2; i < args.Length(); i++)
        argv[i-2] = args[i];

    func->Call(receiver, args.Length()-2, argv);

    delete argv;
    return Undefined();
}
Strings to-and-fro
v8::String -> C string

 Handle<Value> Print(const Arguments &args) {
     HandleScope scope;

     for (int i = 0; i < args.Length(); i++) {
         if (!args[i]->IsString())
             continue;

          // also String::AsciiValue
          String::Utf8Value val(args[i]);
          printf("%s ", *val); // <<<<<<
     }
     return Undefined();
 }
Strings to-and-fro
C string -> v8::String
Handle<Value> Read(const Arguments &args) {
    HandleScope scope;

     char str[1024];
     fgets(str, 1023, stdin);

     Local<String> v8String = String::New(str, strlen(str));
     return scope.Close(v8String);
}

More Related Content

What's hot

Introduction to python
Introduction to pythonIntroduction to python
Introduction to pythonYi-Fan Chu
 
IMPLEMENTING VOICE CONTROL WITH THE ANDROID MEDIA SESSION API ON AMAZON FIRE ...
IMPLEMENTING VOICE CONTROL WITH THE ANDROID MEDIA SESSION API ON AMAZON FIRE ...IMPLEMENTING VOICE CONTROL WITH THE ANDROID MEDIA SESSION API ON AMAZON FIRE ...
IMPLEMENTING VOICE CONTROL WITH THE ANDROID MEDIA SESSION API ON AMAZON FIRE ...Amazon Appstore Developers
 
Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2José Paumard
 
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018John De Goes
 
How to cross compile ROS2 distro by taken VxWorks RTOS as an example
How to cross compile ROS2 distro by taken VxWorks RTOS as an exampleHow to cross compile ROS2 distro by taken VxWorks RTOS as an example
How to cross compile ROS2 distro by taken VxWorks RTOS as an exampleAndrei Kholodnyi
 
RxJava - introduction & design
RxJava - introduction & designRxJava - introduction & design
RxJava - introduction & designallegro.tech
 
Why Rust? - Matthias Endler - Codemotion Amsterdam 2016
Why Rust? - Matthias Endler - Codemotion Amsterdam 2016Why Rust? - Matthias Endler - Codemotion Amsterdam 2016
Why Rust? - Matthias Endler - Codemotion Amsterdam 2016Codemotion
 
Android graphic system (SurfaceFlinger) : Design Pattern's perspective
Android graphic system (SurfaceFlinger) : Design Pattern's perspectiveAndroid graphic system (SurfaceFlinger) : Design Pattern's perspective
Android graphic system (SurfaceFlinger) : Design Pattern's perspectiveBin Chen
 
Android Programming Seminar
Android Programming SeminarAndroid Programming Seminar
Android Programming SeminarNhat Nguyen
 
Node Security: The Good, Bad & Ugly
Node Security: The Good, Bad & UglyNode Security: The Good, Bad & Ugly
Node Security: The Good, Bad & UglyBishan Singh
 
Build responsive applications with google flutter
Build responsive applications with  google flutterBuild responsive applications with  google flutter
Build responsive applications with google flutterAhmed Abu Eldahab
 
Proteus Project : Arduino programming for LED
Proteus Project : Arduino programming for LEDProteus Project : Arduino programming for LED
Proteus Project : Arduino programming for LEDHassan Khan
 
REST and Microservices
REST and MicroservicesREST and Microservices
REST and MicroservicesShaun Abram
 
Android Programming Basics
Android Programming BasicsAndroid Programming Basics
Android Programming BasicsEueung Mulyana
 
What is JavaScript? Edureka
What is JavaScript? EdurekaWhat is JavaScript? Edureka
What is JavaScript? EdurekaEdureka!
 

What's hot (20)

Introduction to python
Introduction to pythonIntroduction to python
Introduction to python
 
IMPLEMENTING VOICE CONTROL WITH THE ANDROID MEDIA SESSION API ON AMAZON FIRE ...
IMPLEMENTING VOICE CONTROL WITH THE ANDROID MEDIA SESSION API ON AMAZON FIRE ...IMPLEMENTING VOICE CONTROL WITH THE ANDROID MEDIA SESSION API ON AMAZON FIRE ...
IMPLEMENTING VOICE CONTROL WITH THE ANDROID MEDIA SESSION API ON AMAZON FIRE ...
 
Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2
 
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
 
How to cross compile ROS2 distro by taken VxWorks RTOS as an example
How to cross compile ROS2 distro by taken VxWorks RTOS as an exampleHow to cross compile ROS2 distro by taken VxWorks RTOS as an example
How to cross compile ROS2 distro by taken VxWorks RTOS as an example
 
Rust Intro
Rust IntroRust Intro
Rust Intro
 
RxJava - introduction & design
RxJava - introduction & designRxJava - introduction & design
RxJava - introduction & design
 
Why Rust? - Matthias Endler - Codemotion Amsterdam 2016
Why Rust? - Matthias Endler - Codemotion Amsterdam 2016Why Rust? - Matthias Endler - Codemotion Amsterdam 2016
Why Rust? - Matthias Endler - Codemotion Amsterdam 2016
 
Android graphic system (SurfaceFlinger) : Design Pattern's perspective
Android graphic system (SurfaceFlinger) : Design Pattern's perspectiveAndroid graphic system (SurfaceFlinger) : Design Pattern's perspective
Android graphic system (SurfaceFlinger) : Design Pattern's perspective
 
Android Programming Seminar
Android Programming SeminarAndroid Programming Seminar
Android Programming Seminar
 
Node Security: The Good, Bad & Ugly
Node Security: The Good, Bad & UglyNode Security: The Good, Bad & Ugly
Node Security: The Good, Bad & Ugly
 
DOT Net overview
DOT Net overviewDOT Net overview
DOT Net overview
 
Build responsive applications with google flutter
Build responsive applications with  google flutterBuild responsive applications with  google flutter
Build responsive applications with google flutter
 
Proteus Project : Arduino programming for LED
Proteus Project : Arduino programming for LEDProteus Project : Arduino programming for LED
Proteus Project : Arduino programming for LED
 
REST and Microservices
REST and MicroservicesREST and Microservices
REST and Microservices
 
Android Programming Basics
Android Programming BasicsAndroid Programming Basics
Android Programming Basics
 
Linux Audio Drivers. ALSA
Linux Audio Drivers. ALSALinux Audio Drivers. ALSA
Linux Audio Drivers. ALSA
 
What is JavaScript? Edureka
What is JavaScript? EdurekaWhat is JavaScript? Edureka
What is JavaScript? Edureka
 
Embedded Android : System Development - Part IV
Embedded Android : System Development - Part IVEmbedded Android : System Development - Part IV
Embedded Android : System Development - Part IV
 
React for Beginners
React for BeginnersReact for Beginners
React for Beginners
 

Viewers also liked

Node.js/io.js Native C++ Addons
Node.js/io.js Native C++ AddonsNode.js/io.js Native C++ Addons
Node.js/io.js Native C++ AddonsChris Barber
 
node-db: La excusa perfecta para hablar de C++ y Node.js
node-db: La excusa perfecta para hablar de C++ y Node.jsnode-db: La excusa perfecta para hablar de C++ y Node.js
node-db: La excusa perfecta para hablar de C++ y Node.jsMariano Iglesias
 
Unleash your inner console cowboy
Unleash your inner console cowboyUnleash your inner console cowboy
Unleash your inner console cowboyKenneth Geisshirt
 
Mastering the IoT With JavaScript and C++ - Günter Obiltschnig
Mastering the IoT With JavaScript and C++ - Günter ObiltschnigMastering the IoT With JavaScript and C++ - Günter Obiltschnig
Mastering the IoT With JavaScript and C++ - Günter ObiltschnigWithTheBest
 
Writing Node.js Bindings - General Principles - Gabriel Schulhof
Writing Node.js Bindings - General Principles - Gabriel SchulhofWriting Node.js Bindings - General Principles - Gabriel Schulhof
Writing Node.js Bindings - General Principles - Gabriel SchulhofWithTheBest
 
Informix - The Ideal Database for IoT
Informix - The Ideal Database for IoTInformix - The Ideal Database for IoT
Informix - The Ideal Database for IoTPradeep Natarajan
 
Preparing for a technical interview
Preparing for a technical interviewPreparing for a technical interview
Preparing for a technical interviewpocketgems
 
How to use Hadoop for operational and transactional purposes by RODRIGO MERI...
 How to use Hadoop for operational and transactional purposes by RODRIGO MERI... How to use Hadoop for operational and transactional purposes by RODRIGO MERI...
How to use Hadoop for operational and transactional purposes by RODRIGO MERI...Big Data Spain
 
Node Foundation Membership Overview 20160907
Node Foundation Membership Overview 20160907Node Foundation Membership Overview 20160907
Node Foundation Membership Overview 20160907NodejsFoundation
 
Functional Programming with Streams in node.js
Functional Programming with Streams in node.jsFunctional Programming with Streams in node.js
Functional Programming with Streams in node.jsAdam Crabtree
 
Linux Profiling at Netflix
Linux Profiling at NetflixLinux Profiling at Netflix
Linux Profiling at NetflixBrendan Gregg
 

Viewers also liked (14)

Node.js/io.js Native C++ Addons
Node.js/io.js Native C++ AddonsNode.js/io.js Native C++ Addons
Node.js/io.js Native C++ Addons
 
Node.js extensions in C++
Node.js extensions in C++Node.js extensions in C++
Node.js extensions in C++
 
Extending Node.js using C++
Extending Node.js using C++Extending Node.js using C++
Extending Node.js using C++
 
node-db: La excusa perfecta para hablar de C++ y Node.js
node-db: La excusa perfecta para hablar de C++ y Node.jsnode-db: La excusa perfecta para hablar de C++ y Node.js
node-db: La excusa perfecta para hablar de C++ y Node.js
 
Unleash your inner console cowboy
Unleash your inner console cowboyUnleash your inner console cowboy
Unleash your inner console cowboy
 
Mastering the IoT With JavaScript and C++ - Günter Obiltschnig
Mastering the IoT With JavaScript and C++ - Günter ObiltschnigMastering the IoT With JavaScript and C++ - Günter Obiltschnig
Mastering the IoT With JavaScript and C++ - Günter Obiltschnig
 
Slidecast power point
Slidecast power pointSlidecast power point
Slidecast power point
 
Writing Node.js Bindings - General Principles - Gabriel Schulhof
Writing Node.js Bindings - General Principles - Gabriel SchulhofWriting Node.js Bindings - General Principles - Gabriel Schulhof
Writing Node.js Bindings - General Principles - Gabriel Schulhof
 
Informix - The Ideal Database for IoT
Informix - The Ideal Database for IoTInformix - The Ideal Database for IoT
Informix - The Ideal Database for IoT
 
Preparing for a technical interview
Preparing for a technical interviewPreparing for a technical interview
Preparing for a technical interview
 
How to use Hadoop for operational and transactional purposes by RODRIGO MERI...
 How to use Hadoop for operational and transactional purposes by RODRIGO MERI... How to use Hadoop for operational and transactional purposes by RODRIGO MERI...
How to use Hadoop for operational and transactional purposes by RODRIGO MERI...
 
Node Foundation Membership Overview 20160907
Node Foundation Membership Overview 20160907Node Foundation Membership Overview 20160907
Node Foundation Membership Overview 20160907
 
Functional Programming with Streams in node.js
Functional Programming with Streams in node.jsFunctional Programming with Streams in node.js
Functional Programming with Streams in node.js
 
Linux Profiling at Netflix
Linux Profiling at NetflixLinux Profiling at Netflix
Linux Profiling at Netflix
 

Similar to Writing native bindings to node.js in C++

In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docx
In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docxIn Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docx
In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docxbradburgess22840
 
Javascript Everywhere
Javascript EverywhereJavascript Everywhere
Javascript EverywherePascal Rettig
 
JVM Mechanics: Understanding the JIT's Tricks
JVM Mechanics: Understanding the JIT's TricksJVM Mechanics: Understanding the JIT's Tricks
JVM Mechanics: Understanding the JIT's TricksDoug Hawkins
 
The uniform interface is 42
The uniform interface is 42The uniform interface is 42
The uniform interface is 42Yevhen Bobrov
 
삼성 바다 앱개발 실패 노하우 2부
삼성 바다 앱개발 실패 노하우 2부삼성 바다 앱개발 실패 노하우 2부
삼성 바다 앱개발 실패 노하우 2부mosaicnet
 
How to Write Node.js Module
How to Write Node.js ModuleHow to Write Node.js Module
How to Write Node.js ModuleFred Chien
 
The Ring programming language version 1.9 book - Part 90 of 210
The Ring programming language version 1.9 book - Part 90 of 210The Ring programming language version 1.9 book - Part 90 of 210
The Ring programming language version 1.9 book - Part 90 of 210Mahmoud Samir Fayed
 
Build Widgets
Build WidgetsBuild Widgets
Build Widgetsscottw
 
Google App Engine Developer - Day3
Google App Engine Developer - Day3Google App Engine Developer - Day3
Google App Engine Developer - Day3Simon Su
 
Agile Iphone Development
Agile Iphone DevelopmentAgile Iphone Development
Agile Iphone DevelopmentGiordano Scalzo
 
JavaScript (without DOM)
JavaScript (without DOM)JavaScript (without DOM)
JavaScript (without DOM)Piyush Katariya
 
Expert JavaScript tricks of the masters
Expert JavaScript  tricks of the mastersExpert JavaScript  tricks of the masters
Expert JavaScript tricks of the mastersAra Pehlivanian
 
OBJECTS IN Object Oriented Programming .ppt
OBJECTS IN Object Oriented Programming .pptOBJECTS IN Object Oriented Programming .ppt
OBJECTS IN Object Oriented Programming .pptSaadAsim11
 
JJUG CCC 2011 Spring
JJUG CCC 2011 SpringJJUG CCC 2011 Spring
JJUG CCC 2011 SpringKiyotaka Oku
 
Reactive programming with RxJava
Reactive programming with RxJavaReactive programming with RxJava
Reactive programming with RxJavaJobaer Chowdhury
 
Reactive programming on Android
Reactive programming on AndroidReactive programming on Android
Reactive programming on AndroidTomáš Kypta
 
Java script advance-auroskills (2)
Java script advance-auroskills (2)Java script advance-auroskills (2)
Java script advance-auroskills (2)BoneyGawande
 

Similar to Writing native bindings to node.js in C++ (20)

In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docx
In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docxIn Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docx
In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docx
 
Javascript Everywhere
Javascript EverywhereJavascript Everywhere
Javascript Everywhere
 
JVM Mechanics: Understanding the JIT's Tricks
JVM Mechanics: Understanding the JIT's TricksJVM Mechanics: Understanding the JIT's Tricks
JVM Mechanics: Understanding the JIT's Tricks
 
The uniform interface is 42
The uniform interface is 42The uniform interface is 42
The uniform interface is 42
 
Day 1
Day 1Day 1
Day 1
 
V8
V8V8
V8
 
삼성 바다 앱개발 실패 노하우 2부
삼성 바다 앱개발 실패 노하우 2부삼성 바다 앱개발 실패 노하우 2부
삼성 바다 앱개발 실패 노하우 2부
 
How to Write Node.js Module
How to Write Node.js ModuleHow to Write Node.js Module
How to Write Node.js Module
 
The Ring programming language version 1.9 book - Part 90 of 210
The Ring programming language version 1.9 book - Part 90 of 210The Ring programming language version 1.9 book - Part 90 of 210
The Ring programming language version 1.9 book - Part 90 of 210
 
Build Widgets
Build WidgetsBuild Widgets
Build Widgets
 
Google App Engine Developer - Day3
Google App Engine Developer - Day3Google App Engine Developer - Day3
Google App Engine Developer - Day3
 
Agile Iphone Development
Agile Iphone DevelopmentAgile Iphone Development
Agile Iphone Development
 
JavaScript (without DOM)
JavaScript (without DOM)JavaScript (without DOM)
JavaScript (without DOM)
 
Expert JavaScript tricks of the masters
Expert JavaScript  tricks of the mastersExpert JavaScript  tricks of the masters
Expert JavaScript tricks of the masters
 
OBJECTS IN Object Oriented Programming .ppt
OBJECTS IN Object Oriented Programming .pptOBJECTS IN Object Oriented Programming .ppt
OBJECTS IN Object Oriented Programming .ppt
 
JJUG CCC 2011 Spring
JJUG CCC 2011 SpringJJUG CCC 2011 Spring
JJUG CCC 2011 Spring
 
Reactive programming with RxJava
Reactive programming with RxJavaReactive programming with RxJava
Reactive programming with RxJava
 
Reactive programming on Android
Reactive programming on AndroidReactive programming on Android
Reactive programming on Android
 
Java script advance-auroskills (2)
Java script advance-auroskills (2)Java script advance-auroskills (2)
Java script advance-auroskills (2)
 
I os 04
I os 04I os 04
I os 04
 

Recently uploaded

Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
The Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfThe Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfSeasiaInfotech2
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 

Recently uploaded (20)

Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
The Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfThe Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdf
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 

Writing native bindings to node.js in C++

  • 1. Build the C link Nikhil Marathe
  • 2. 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)
  • 3. Follow along Slides and code git clone git://github.com/nikhilm/jsfoo-pune-2012.git
  • 4. We want to Use C/C++ libraries in node.js Exchange data between C++ ⇔ JS Do asynchronous I/O
  • 5. Getting started #include <v8.h> #include <node.h> using namespace v8; extern "C" { static void Init(Handle<Object> target) { } NODE_MODULE(firststep, Init) }
  • 6. Build # firststep/wscript import Options def set_options(opt): opt.tool_options("compiler_cxx") def configure(conf): conf.check_tool("compiler_cxx") conf.check_tool("node_addon") def build(bld): obj = bld.new_task_gen("cxx", "shlib", "node_addon") obj.target = "firststep" obj.source = "firststep.cc"
  • 7. Run $ node-waf configure build ... 'build' finished successfully (0.327s) $ node > require('./build/Release/firststep') {}
  • 8. Architecture 1 you will need http://bespin.cz/~ondras/html/index.html
  • 9.
  • 10. 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;
  • 11. Injecting primitives #include <math.h> #include <v8.h> #include <node.h> #include <node_version.h> using namespace v8; extern "C" { static void Init(Handle<Object> target) { target->Set(String::NewSymbol("pi"), Number::New(M_PI)); NODE_DEFINE_CONSTANT(target, NODE_MINOR_VERSION); target->Set(String::New("name"), String::New("Nikhil")); } NODE_MODULE(primitives, Init) }
  • 12. Simple functions exports.square = function(n) { return n * n; } We want to do this in C++
  • 13. Simple functions Registering with V8: Handle<Value> Square(const Arguments &args) static void Init(Handle<Object> target) { HandleScope scope; Handle<FunctionTemplate> squareTpl = FunctionTemplate::New(Square); target->Set(String::New("square"), squareTpl->GetFunction()); }
  • 14. Simple functions Implementation: Handle<Value> Square(const Arguments &args) { HandleScope scope; int a = args[0]->Int32Value(); int sq = a * a; return scope.Close(Integer::New(sq)); } explain scope.Close
  • 15. Templates FunctionTemplate ??? FunctionTemplate::GetFunction square [Function] FunctionTemplate::InstanceTemplate() What `this` would be in 'new square()' FunctionTemplate::PrototypeTemplate() square.prototype
  • 16. 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
  • 17. Simple objects static void Init(Handle<Object> target) { HandleScope scope; Handle<FunctionTemplate> inventoryTpl = FunctionTemplate::New(Inventory); Handle<ObjectTemplate> instance = inventoryTpl->InstanceTemplate(); instance->Set(String::New("items"), Integer::New(257)); target->Set(String::NewSymbol("Inventory"), inventoryTpl->GetFunction()); } Handle<Value> Inventory(const Arguments &args) { return args.This();
  • 18. }
  • 19. 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 }
  • 20. Methods Registering prototype methods // operating on inventoryTpl->PrototypeTemplate() NODE_SET_PROTOTYPE_METHOD(inventoryTpl, "addStock", AddStock); NODE_SET_PROTOTYPE_METHOD(inventoryTpl, "ship", Ship); target->Set(String::NewSymbol("Inventory"), inventoryTpl->GetFunction());
  • 21. Methods Accessing object properties Handle<Value> AddStock(const Arguments &args) { HandleScope scope; Handle<Object> This = args.This(); int items = This->Get(String::New("items"))->Uint32Value(); items += args[0]->Uint32Value(); This->Set(String::New("items"), Integer::New(items)); return Undefined(); }
  • 22. Methods Throwing an exception Handle<Value> Ship(const Arguments &args) { HandleScope scope; Handle<Object> This = args.This(); int items = This->Get(String::New("items"))->Uint32Value(); int orders = args[0]->Uint32Value(); if (items < orders) return ThrowException(String::New("Not enough items")); This->Set(String::New("items"), Integer::New(items - orders)); return Undefined(); }
  • 23. ObjectWrap • Associate native C++ objects with JS objects • Node specific class which manages garbage collection • Stored internally in fields
  • 24. ObjectWrap // native C++ class namespace Library { class Inventory { Inventory(); void addStock(int); int ship(int); int getItems(); int items; // private }; }
  • 25. ObjectWrap Setting internal field count Handle<ObjectTemplate> instance = inventoryTpl->InstanceTemplate(); instance->SetInternalFieldCount(1);
  • 26. ObjectWrap Wrapping namespace binding { class Inventory : public ObjectWrap { public: static Handle<Value> New(const Arguments &args) { Inventory *wrapper = new Inventory(); wrapper->Wrap(args.Holder()); return args.Holder(); }
  • 27. ObjectWrap Unwrapping static Handle<Value> Ship(const Arguments &args) { // extract Inventory *wrapper = Unwrap<Inventory>(args.Holder()); int orders = args[0]->Uint32Value(); int result = wrapper->inv->ship(orders); if (result == -1) return ThrowException(String::New("Not enough items")); return Undefined(); }
  • 28. 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 :(
  • 29. Going Async var inv = new (require('./build/Release/async')).Inventory() inv.reshelve(function() { console.log("Reshelving done"); }) console.log("After reshelve in source"); for (var i = 1; i < 5; i++) setTimeout(function() { console.log("Tick"); }, i*1000);
  • 30. Going Async The native blocking code (method of class Library::Inventory) void reshelve() { sleep(5); }
  • 31. Going Async The baton struct ReshelveBaton { uv_work_t request; Persistent<Function> callback; Inventory *wrapper; // any other data that has to be sent to the callback // or for async processing. }
  • 32. Going Async JS callback static Handle<Value> Reshelve(const Arguments &args) { Inventory *wrapper = Unwrap<Inventory>(args.Holder()); Handle<Function> cb = Handle<Function>::Cast(args[0]); ReshelveBaton *baton = new ReshelveBaton(); baton->request.data = baton; baton->callback = Persistent<Function>::New(cb); baton->wrapper = wrapper; uv_queue_work(Loop(), &baton->request, ReshelveAsync, ReshelveAsyncAfter); return Undefined(); }
  • 33. Going Async Thread pool function static void ReshelveAsync(uv_work_t *req) { // This runs in a separate thread // NO V8 interaction should be done ReshelveBaton *baton = static_cast<ReshelveBaton*>(req->data); // if you want to modify baton values // do synchronous work here baton->wrapper->inv->reshelve(); }
  • 34. Going Async Clean up static void ReshelveAsyncAfter(uv_work_t *req) { ReshelveBaton *baton = static_cast<ReshelveBaton*>(req->data); Handle<Value> argv[] = { Null() }; // no error baton->callback->Call(Context::GetCurrent()->Global(), 1, argv); baton->callback.Dispose(); delete baton; }
  • 35. Going Async Output After reshelve in source Tick Tick Tick Tick Reshelving done
  • 36. 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'
  • 37. 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
  • 38. 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
  • 39. You might want to look at • https://github.com/weaver/uuidjs • https://github.com/nikhilm/node-taglib • https://github.com/pietern/hiredis-node
  • 40. End notes Contact: • @nikhilcutshort • nsm.nikhil@gmail.com Cover image by Munjal Savla (by-nc-sa)
  • 42. Calling JS functions var calljs = require("./build/Release/calljs") var f = function() { console.log("This", this); console.log(arguments); } calljs.apply(f, { cool: "dude" }, "one", 2, 3.14);
  • 43. Calling JS functions Handle<Value> Apply(const Arguments &args) { HandleScope scope; Handle<Function> func = Handle<Function>::Cast(args[0]); Handle<Object> receiver = args[1]->ToObject(); Handle<Value> *argv = new Handle<Value>[args.Length() - 2]; for (int i = 2; i < args.Length(); i++) argv[i-2] = args[i]; func->Call(receiver, args.Length()-2, argv); delete argv; return Undefined(); }
  • 44. Strings to-and-fro v8::String -> C string Handle<Value> Print(const Arguments &args) { HandleScope scope; for (int i = 0; i < args.Length(); i++) { if (!args[i]->IsString()) continue; // also String::AsciiValue String::Utf8Value val(args[i]); printf("%s ", *val); // <<<<<< } return Undefined(); }
  • 45. Strings to-and-fro C string -> v8::String Handle<Value> Read(const Arguments &args) { HandleScope scope; char str[1024]; fgets(str, 1023, stdin); Local<String> v8String = String::New(str, strlen(str)); return scope.Close(v8String); }