3 Addons are dynamically linked shared objects. They can provide glue to C and
4 C++ libraries. The API (at the moment) is rather complex, involving
5 knowledge of several libraries:
7 - V8 JavaScript, a C++ library. Used for interfacing with JavaScript:
8 creating objects, calling functions, etc. Documented mostly in the
9 `v8.h` header file (`deps/v8/include/v8.h` in the Node source
10 tree), which is also available
11 [online](http://izs.me/v8-docs/main.html).
13 - [libuv](https://github.com/joyent/libuv), C event loop library.
14 Anytime one needs to wait for a file descriptor to become readable,
15 wait for a timer, or wait for a signal to be received one will need
16 to interface with libuv. That is, if you perform any I/O, libuv will
19 - Internal Node libraries. Most importantly is the `node::ObjectWrap`
20 class which you will likely want to derive from.
22 - Others. Look in `deps/` for what else is available.
24 Node statically compiles all its dependencies into the executable.
25 When compiling your module, you don't need to worry about linking to
26 any of these libraries.
28 All of the following examples are available for
29 [download](https://github.com/rvagg/node-addon-examples) and may be
30 used as a starting-point for your own Addon.
34 To get started let's make a small Addon which is the C++ equivalent of
35 the following JavaScript code:
37 module.exports.hello = function() { return 'world'; };
39 First we create a file `hello.cc`:
44 Isolate* isolate = Isolate::GetCurrent();
48 Handle<Value> Method(const Arguments& args) {
49 HandleScope scope(isolate);
50 return scope.Close(String::New("world"));
53 void init(Handle<Object> exports) {
54 exports->Set(String::NewSymbol("hello"),
55 FunctionTemplate::New(Method)->GetFunction());
58 NODE_MODULE(hello, init)
60 Note that all Node addons must export an initialization function:
62 void Initialize (Handle<Object> exports);
63 NODE_MODULE(module_name, Initialize)
65 There is no semi-colon after `NODE_MODULE` as it's not a function (see `node.h`).
67 The `module_name` needs to match the filename of the final binary (minus the
70 The source code needs to be built into `hello.node`, the binary Addon. To
71 do this we create a file called `binding.gyp` which describes the configuration
72 to build your module in a JSON-like format. This file gets compiled by
73 [node-gyp](https://github.com/TooTallNate/node-gyp).
78 "target_name": "hello",
79 "sources": [ "hello.cc" ]
84 The next step is to generate the appropriate project build files for the
85 current platform. Use `node-gyp configure` for that.
87 Now you will have either a `Makefile` (on Unix platforms) or a `vcxproj` file
88 (on Windows) in the `build/` directory. Next invoke the `node-gyp build`
91 Now you have your compiled `.node` bindings file! The compiled bindings end up
94 You can now use the binary addon in a Node project `hello.js` by pointing `require` to
95 the recently built `hello.node` module:
97 var addon = require('./build/Release/hello');
99 console.log(addon.hello()); // 'world'
101 Please see patterns below for further information or
102 <https://github.com/arturadib/node-qt> for an example in production.
107 Below are some addon patterns to help you get started. Consult the online
108 [v8 reference](http://izs.me/v8-docs/main.html) for help with the various v8
109 calls, and v8's [Embedder's Guide](http://code.google.com/apis/v8/embed.html)
110 for an explanation of several concepts used such as handles, scopes,
111 function templates, etc.
113 In order to use these examples you need to compile them using `node-gyp`.
114 Create the following `binding.gyp` file:
119 "target_name": "addon",
120 "sources": [ "addon.cc" ]
125 In cases where there is more than one `.cc` file, simply add the file name to the
126 `sources` array, e.g.:
128 "sources": ["addon.cc", "myexample.cc"]
130 Now that you have your `binding.gyp` ready, you can configure and build the
133 $ node-gyp configure build
136 ### Function arguments
138 The following pattern illustrates how to read arguments from JavaScript
139 function calls and return a result. This is the main and only needed source
142 #define BUILDING_NODE_EXTENSION
145 Isolate* isolate = Isolate::GetCurrent();
149 Handle<Value> Add(const Arguments& args) {
150 HandleScope scope(isolate);
152 if (args.Length() < 2) {
153 ThrowException(Exception::TypeError(String::New("Wrong number of arguments")));
154 return scope.Close(Undefined(isolate));
157 if (!args[0]->IsNumber() || !args[1]->IsNumber()) {
158 ThrowException(Exception::TypeError(String::New("Wrong arguments")));
159 return scope.Close(Undefined(isolate));
162 Local<Number> num = Number::New(args[0]->NumberValue() +
163 args[1]->NumberValue());
164 return scope.Close(num);
167 void Init(Handle<Object> exports) {
168 exports->Set(String::NewSymbol("add"),
169 FunctionTemplate::New(Add)->GetFunction());
172 NODE_MODULE(addon, Init)
174 You can test it with the following JavaScript snippet:
176 var addon = require('./build/Release/addon');
178 console.log( 'This should be eight:', addon.add(3,5) );
183 You can pass JavaScript functions to a C++ function and execute them from
184 there. Here's `addon.cc`:
186 #define BUILDING_NODE_EXTENSION
189 Isolate* isolate = Isolate::GetCurrent();
193 Handle<Value> RunCallback(const Arguments& args) {
194 HandleScope scope(isolate);
196 Local<Function> cb = Local<Function>::Cast(args[0]);
197 const unsigned argc = 1;
198 Local<Value> argv[argc] = { Local<Value>::New(String::New("hello world")) };
199 cb->Call(Context::GetCurrent()->Global(), argc, argv);
201 return scope.Close(Undefined(isolate));
204 void Init(Handle<Object> exports, Handle<Object> module) {
205 module->Set(String::NewSymbol("exports"),
206 FunctionTemplate::New(RunCallback)->GetFunction());
209 NODE_MODULE(addon, Init)
211 Note that this example uses a two-argument form of `Init()` that receives
212 the full `module` object as the second argument. This allows the addon
213 to completely overwrite `exports` with a single function instead of
214 adding the function as a property of `exports`.
216 To test it run the following JavaScript snippet:
218 var addon = require('./build/Release/addon');
221 console.log(msg); // 'hello world'
227 You can create and return new objects from within a C++ function with this
228 `addon.cc` pattern, which returns an object with property `msg` that echoes
229 the string passed to `createObject()`:
231 #define BUILDING_NODE_EXTENSION
234 Isolate* isolate = Isolate::GetCurrent();
238 Handle<Value> CreateObject(const Arguments& args) {
239 HandleScope scope(isolate);
241 Local<Object> obj = Object::New();
242 obj->Set(String::NewSymbol("msg"), args[0]->ToString());
244 return scope.Close(obj);
247 void Init(Handle<Object> exports, Handle<Object> module) {
248 module->Set(String::NewSymbol("exports"),
249 FunctionTemplate::New(CreateObject)->GetFunction());
252 NODE_MODULE(addon, Init)
254 To test it in JavaScript:
256 var addon = require('./build/Release/addon');
258 var obj1 = addon('hello');
259 var obj2 = addon('world');
260 console.log(obj1.msg+' '+obj2.msg); // 'hello world'
265 This pattern illustrates how to create and return a JavaScript function that
266 wraps a C++ function:
268 #define BUILDING_NODE_EXTENSION
271 Isolate* isolate = Isolate::GetCurrent();
275 Handle<Value> MyFunction(const Arguments& args) {
276 HandleScope scope(isolate);
277 return scope.Close(String::New("hello world"));
280 Handle<Value> CreateFunction(const Arguments& args) {
281 HandleScope scope(isolate);
283 Local<FunctionTemplate> tpl = FunctionTemplate::New(MyFunction);
284 Local<Function> fn = tpl->GetFunction();
285 fn->SetName(String::NewSymbol("theFunction")); // omit this to make it anonymous
287 return scope.Close(fn);
290 void Init(Handle<Object> exports, Handle<Object> module) {
291 module->Set(String::NewSymbol("exports"),
292 FunctionTemplate::New(CreateFunction)->GetFunction());
295 NODE_MODULE(addon, Init)
300 var addon = require('./build/Release/addon');
303 console.log(fn()); // 'hello world'
306 ### Wrapping C++ objects
308 Here we will create a wrapper for a C++ object/class `MyObject` that can be
309 instantiated in JavaScript through the `new` operator. First prepare the main
312 #define BUILDING_NODE_EXTENSION
314 #include "myobject.h"
318 void InitAll(Handle<Object> exports) {
319 MyObject::Init(exports);
322 NODE_MODULE(addon, InitAll)
324 Then in `myobject.h` make your wrapper inherit from `node::ObjectWrap`:
331 class MyObject : public node::ObjectWrap {
333 static void Init(v8::Handle<v8::Object> exports);
339 static v8::Handle<v8::Value> New(const v8::Arguments& args);
340 static v8::Handle<v8::Value> PlusOne(const v8::Arguments& args);
346 And in `myobject.cc` implement the various methods that you want to expose.
347 Here we expose the method `plusOne` by adding it to the constructor's
350 #define BUILDING_NODE_EXTENSION
352 #include "myobject.h"
354 Isolate* isolate = Isolate::GetCurrent();
358 MyObject::MyObject() {};
359 MyObject::~MyObject() {};
361 void MyObject::Init(Handle<Object> exports) {
362 // Prepare constructor template
363 Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
364 tpl->SetClassName(String::NewSymbol("MyObject"));
365 tpl->InstanceTemplate()->SetInternalFieldCount(1);
367 tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"),
368 FunctionTemplate::New(PlusOne)->GetFunction());
370 Persistent<Function> constructor = Persistent<Function>::New(isolate, tpl->GetFunction());
371 exports->Set(String::NewSymbol("MyObject"), constructor);
374 Handle<Value> MyObject::New(const Arguments& args) {
375 HandleScope scope(isolate);
377 MyObject* obj = new MyObject();
378 obj->counter_ = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
379 obj->Wrap(args.This());
384 Handle<Value> MyObject::PlusOne(const Arguments& args) {
385 HandleScope scope(isolate);
387 MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());
390 return scope.Close(Number::New(obj->counter_));
395 var addon = require('./build/Release/addon');
397 var obj = new addon.MyObject(10);
398 console.log( obj.plusOne() ); // 11
399 console.log( obj.plusOne() ); // 12
400 console.log( obj.plusOne() ); // 13
403 ### Factory of wrapped objects
405 This is useful when you want to be able to create native objects without
406 explicitly instantiating them with the `new` operator in JavaScript, e.g.
408 var obj = addon.createObject();
410 // var obj = new addon.Object();
412 Let's register our `createObject` method in `addon.cc`:
414 #define BUILDING_NODE_EXTENSION
416 #include "myobject.h"
418 Isolate* isolate = Isolate::GetCurrent();
422 Handle<Value> CreateObject(const Arguments& args) {
423 HandleScope scope(isolate);
424 return scope.Close(MyObject::NewInstance(args));
427 void InitAll(Handle<Object> exports, Handle<Object> module) {
430 module->Set(String::NewSymbol("exports"),
431 FunctionTemplate::New(CreateObject)->GetFunction());
434 NODE_MODULE(addon, InitAll)
436 In `myobject.h` we now introduce the static method `NewInstance` that takes
437 care of instantiating the object (i.e. it does the job of `new` in JavaScript):
439 #define BUILDING_NODE_EXTENSION
445 class MyObject : public node::ObjectWrap {
448 static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);
454 static v8::Persistent<v8::Function> constructor;
455 static v8::Handle<v8::Value> New(const v8::Arguments& args);
456 static v8::Handle<v8::Value> PlusOne(const v8::Arguments& args);
462 The implementation is similar to the above in `myobject.cc`:
464 #define BUILDING_NODE_EXTENSION
466 #include "myobject.h"
468 Isolate* isolate = Isolate::GetCurrent();
472 MyObject::MyObject() {};
473 MyObject::~MyObject() {};
475 Persistent<Function> MyObject::constructor;
477 void MyObject::Init() {
478 // Prepare constructor template
479 Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
480 tpl->SetClassName(String::NewSymbol("MyObject"));
481 tpl->InstanceTemplate()->SetInternalFieldCount(1);
483 tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"),
484 FunctionTemplate::New(PlusOne)->GetFunction());
486 constructor = Persistent<Function>::New(isolate, tpl->GetFunction());
489 Handle<Value> MyObject::New(const Arguments& args) {
490 HandleScope scope(isolate);
492 MyObject* obj = new MyObject();
493 obj->counter_ = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
494 obj->Wrap(args.This());
499 Handle<Value> MyObject::NewInstance(const Arguments& args) {
500 HandleScope scope(isolate);
502 const unsigned argc = 1;
503 Handle<Value> argv[argc] = { args[0] };
504 Local<Object> instance = constructor->NewInstance(argc, argv);
506 return scope.Close(instance);
509 Handle<Value> MyObject::PlusOne(const Arguments& args) {
510 HandleScope scope(isolate);
512 MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());
515 return scope.Close(Number::New(obj->counter_));
520 var createObject = require('./build/Release/addon');
522 var obj = createObject(10);
523 console.log( obj.plusOne() ); // 11
524 console.log( obj.plusOne() ); // 12
525 console.log( obj.plusOne() ); // 13
527 var obj2 = createObject(20);
528 console.log( obj2.plusOne() ); // 21
529 console.log( obj2.plusOne() ); // 22
530 console.log( obj2.plusOne() ); // 23
533 ### Passing wrapped objects around
535 In addition to wrapping and returning C++ objects, you can pass them around
536 by unwrapping them with Node's `node::ObjectWrap::Unwrap` helper function.
537 In the following `addon.cc` we introduce a function `add()` that can take on two
540 #define BUILDING_NODE_EXTENSION
542 #include "myobject.h"
544 Isolate* isolate = Isolate::GetCurrent();
548 Handle<Value> CreateObject(const Arguments& args) {
549 HandleScope scope(isolate);
550 return scope.Close(MyObject::NewInstance(args));
553 Handle<Value> Add(const Arguments& args) {
554 HandleScope scope(isolate);
556 MyObject* obj1 = node::ObjectWrap::Unwrap<MyObject>(
557 args[0]->ToObject());
558 MyObject* obj2 = node::ObjectWrap::Unwrap<MyObject>(
559 args[1]->ToObject());
561 double sum = obj1->Val() + obj2->Val();
562 return scope.Close(Number::New(sum));
565 void InitAll(Handle<Object> exports) {
568 exports->Set(String::NewSymbol("createObject"),
569 FunctionTemplate::New(CreateObject)->GetFunction());
571 exports->Set(String::NewSymbol("add"),
572 FunctionTemplate::New(Add)->GetFunction());
575 NODE_MODULE(addon, InitAll)
577 To make things interesting we introduce a public method in `myobject.h` so we
578 can probe private values after unwrapping the object:
580 #define BUILDING_NODE_EXTENSION
586 class MyObject : public node::ObjectWrap {
589 static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);
590 double Val() const { return val_; }
596 static v8::Persistent<v8::Function> constructor;
597 static v8::Handle<v8::Value> New(const v8::Arguments& args);
603 The implementation of `myobject.cc` is similar as before:
605 #define BUILDING_NODE_EXTENSION
607 #include "myobject.h"
609 Isolate* isolate = Isolate::GetCurrent();
613 MyObject::MyObject() {};
614 MyObject::~MyObject() {};
616 Persistent<Function> MyObject::constructor;
618 void MyObject::Init() {
619 // Prepare constructor template
620 Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
621 tpl->SetClassName(String::NewSymbol("MyObject"));
622 tpl->InstanceTemplate()->SetInternalFieldCount(1);
624 constructor = Persistent<Function>::New(tpl->GetFunction());
627 Handle<Value> MyObject::New(const Arguments& args) {
628 HandleScope scope(isolate);
630 MyObject* obj = new MyObject();
631 obj->val_ = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
632 obj->Wrap(args.This());
637 Handle<Value> MyObject::NewInstance(const Arguments& args) {
638 HandleScope scope(isolate);
640 const unsigned argc = 1;
641 Handle<Value> argv[argc] = { args[0] };
642 Local<Object> instance = constructor->NewInstance(argc, argv);
644 return scope.Close(instance);
649 var addon = require('./build/Release/addon');
651 var obj1 = addon.createObject(10);
652 var obj2 = addon.createObject(20);
653 var result = addon.add(obj1, obj2);
655 console.log(result); // 30