Merge remote-tracking branch 'ry/v0.10'
[platform/upstream/nodejs.git] / doc / api / addons.markdown
1 # Addons
2
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:
6
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).
12
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
17    need to be used.
18
19  - Internal Node libraries. Most importantly is the `node::ObjectWrap`
20    class which you will likely want to derive from.
21
22  - Others. Look in `deps/` for what else is available.
23
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.
27
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.
31
32 ## Hello world
33
34 To get started let's make a small Addon which is the C++ equivalent of
35 the following JavaScript code:
36
37     module.exports.hello = function() { return 'world'; };
38
39 First we create a file `hello.cc`:
40
41     #include <node.h>
42     #include <v8.h>
43
44     Isolate* isolate = Isolate::GetCurrent();
45
46     using namespace v8;
47
48     Handle<Value> Method(const Arguments& args) {
49       HandleScope scope(isolate);
50       return scope.Close(String::New("world"));
51     }
52
53     void init(Handle<Object> exports) {
54       exports->Set(String::NewSymbol("hello"),
55           FunctionTemplate::New(Method)->GetFunction());
56     }
57
58     NODE_MODULE(hello, init)
59
60 Note that all Node addons must export an initialization function:
61
62     void Initialize (Handle<Object> exports);
63     NODE_MODULE(module_name, Initialize)
64
65 There is no semi-colon after `NODE_MODULE` as it's not a function (see `node.h`).
66
67 The `module_name` needs to match the filename of the final binary (minus the
68 .node suffix).
69
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).
74
75     {
76       "targets": [
77         {
78           "target_name": "hello",
79           "sources": [ "hello.cc" ]
80         }
81       ]
82     }
83
84 The next step is to generate the appropriate project build files for the
85 current platform. Use `node-gyp configure` for that.
86
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`
89 command.
90
91 Now you have your compiled `.node` bindings file! The compiled bindings end up
92 in `build/Release/`.
93
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:
96
97     var addon = require('./build/Release/hello');
98
99     console.log(addon.hello()); // 'world'
100
101 Please see patterns below for further information or
102 <https://github.com/arturadib/node-qt> for an example in production.
103
104
105 ## Addon patterns
106
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.
112
113 In order to use these examples you need to compile them using `node-gyp`.
114 Create the following `binding.gyp` file:
115
116     {
117       "targets": [
118         {
119           "target_name": "addon",
120           "sources": [ "addon.cc" ]
121         }
122       ]
123     }
124
125 In cases where there is more than one `.cc` file, simply add the file name to the
126 `sources` array, e.g.:
127
128     "sources": ["addon.cc", "myexample.cc"]
129
130 Now that you have your `binding.gyp` ready, you can configure and build the
131 addon:
132
133     $ node-gyp configure build
134
135
136 ### Function arguments
137
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
140 `addon.cc`:
141
142     #define BUILDING_NODE_EXTENSION
143     #include <node.h>
144
145     Isolate* isolate = Isolate::GetCurrent();
146
147     using namespace v8;
148
149     Handle<Value> Add(const Arguments& args) {
150       HandleScope scope(isolate);
151
152       if (args.Length() < 2) {
153         ThrowException(Exception::TypeError(String::New("Wrong number of arguments")));
154         return scope.Close(Undefined(isolate));
155       }
156
157       if (!args[0]->IsNumber() || !args[1]->IsNumber()) {
158         ThrowException(Exception::TypeError(String::New("Wrong arguments")));
159         return scope.Close(Undefined(isolate));
160       }
161
162       Local<Number> num = Number::New(args[0]->NumberValue() +
163           args[1]->NumberValue());
164       return scope.Close(num);
165     }
166
167     void Init(Handle<Object> exports) {
168       exports->Set(String::NewSymbol("add"),
169           FunctionTemplate::New(Add)->GetFunction());
170     }
171
172     NODE_MODULE(addon, Init)
173
174 You can test it with the following JavaScript snippet:
175
176     var addon = require('./build/Release/addon');
177
178     console.log( 'This should be eight:', addon.add(3,5) );
179
180
181 ### Callbacks
182
183 You can pass JavaScript functions to a C++ function and execute them from
184 there. Here's `addon.cc`:
185
186     #define BUILDING_NODE_EXTENSION
187     #include <node.h>
188
189     Isolate* isolate = Isolate::GetCurrent();
190
191     using namespace v8;
192
193     Handle<Value> RunCallback(const Arguments& args) {
194       HandleScope scope(isolate);
195
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);
200
201       return scope.Close(Undefined(isolate));
202     }
203
204     void Init(Handle<Object> exports, Handle<Object> module) {
205       module->Set(String::NewSymbol("exports"),
206           FunctionTemplate::New(RunCallback)->GetFunction());
207     }
208
209     NODE_MODULE(addon, Init)
210
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`.
215
216 To test it run the following JavaScript snippet:
217
218     var addon = require('./build/Release/addon');
219
220     addon(function(msg){
221       console.log(msg); // 'hello world'
222     });
223
224
225 ### Object factory
226
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()`:
230
231     #define BUILDING_NODE_EXTENSION
232     #include <node.h>
233
234     Isolate* isolate = Isolate::GetCurrent();
235
236     using namespace v8;
237
238     Handle<Value> CreateObject(const Arguments& args) {
239       HandleScope scope(isolate);
240
241       Local<Object> obj = Object::New();
242       obj->Set(String::NewSymbol("msg"), args[0]->ToString());
243
244       return scope.Close(obj);
245     }
246
247     void Init(Handle<Object> exports, Handle<Object> module) {
248       module->Set(String::NewSymbol("exports"),
249           FunctionTemplate::New(CreateObject)->GetFunction());
250     }
251
252     NODE_MODULE(addon, Init)
253
254 To test it in JavaScript:
255
256     var addon = require('./build/Release/addon');
257
258     var obj1 = addon('hello');
259     var obj2 = addon('world');
260     console.log(obj1.msg+' '+obj2.msg); // 'hello world'
261
262
263 ### Function factory
264
265 This pattern illustrates how to create and return a JavaScript function that
266 wraps a C++ function:
267
268     #define BUILDING_NODE_EXTENSION
269     #include <node.h>
270
271     Isolate* isolate = Isolate::GetCurrent();
272
273     using namespace v8;
274
275     Handle<Value> MyFunction(const Arguments& args) {
276       HandleScope scope(isolate);
277       return scope.Close(String::New("hello world"));
278     }
279
280     Handle<Value> CreateFunction(const Arguments& args) {
281       HandleScope scope(isolate);
282
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
286
287       return scope.Close(fn);
288     }
289
290     void Init(Handle<Object> exports, Handle<Object> module) {
291       module->Set(String::NewSymbol("exports"),
292           FunctionTemplate::New(CreateFunction)->GetFunction());
293     }
294
295     NODE_MODULE(addon, Init)
296
297
298 To test:
299
300     var addon = require('./build/Release/addon');
301
302     var fn = addon();
303     console.log(fn()); // 'hello world'
304
305
306 ### Wrapping C++ objects
307
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
310 module `addon.cc`:
311
312     #define BUILDING_NODE_EXTENSION
313     #include <node.h>
314     #include "myobject.h"
315
316     using namespace v8;
317
318     void InitAll(Handle<Object> exports) {
319       MyObject::Init(exports);
320     }
321
322     NODE_MODULE(addon, InitAll)
323
324 Then in `myobject.h` make your wrapper inherit from `node::ObjectWrap`:
325
326     #ifndef MYOBJECT_H
327     #define MYOBJECT_H
328
329     #include <node.h>
330
331     class MyObject : public node::ObjectWrap {
332      public:
333       static void Init(v8::Handle<v8::Object> exports);
334
335      private:
336       MyObject();
337       ~MyObject();
338
339       static v8::Handle<v8::Value> New(const v8::Arguments& args);
340       static v8::Handle<v8::Value> PlusOne(const v8::Arguments& args);
341       double counter_;
342     };
343
344     #endif
345
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
348 prototype:
349
350     #define BUILDING_NODE_EXTENSION
351     #include <node.h>
352     #include "myobject.h"
353
354     Isolate* isolate = Isolate::GetCurrent();
355
356     using namespace v8;
357
358     MyObject::MyObject() {};
359     MyObject::~MyObject() {};
360
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);
366       // Prototype
367       tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"),
368           FunctionTemplate::New(PlusOne)->GetFunction());
369
370       Persistent<Function> constructor = Persistent<Function>::New(isolate, tpl->GetFunction());
371       exports->Set(String::NewSymbol("MyObject"), constructor);
372     }
373
374     Handle<Value> MyObject::New(const Arguments& args) {
375       HandleScope scope(isolate);
376
377       MyObject* obj = new MyObject();
378       obj->counter_ = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
379       obj->Wrap(args.This());
380
381       return args.This();
382     }
383
384     Handle<Value> MyObject::PlusOne(const Arguments& args) {
385       HandleScope scope(isolate);
386
387       MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());
388       obj->counter_ += 1;
389
390       return scope.Close(Number::New(obj->counter_));
391     }
392
393 Test it with:
394
395     var addon = require('./build/Release/addon');
396
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
401
402
403 ### Factory of wrapped objects
404
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.
407
408     var obj = addon.createObject();
409     // instead of:
410     // var obj = new addon.Object();
411
412 Let's register our `createObject` method in `addon.cc`:
413
414     #define BUILDING_NODE_EXTENSION
415     #include <node.h>
416     #include "myobject.h"
417
418     Isolate* isolate = Isolate::GetCurrent();
419
420     using namespace v8;
421
422     Handle<Value> CreateObject(const Arguments& args) {
423       HandleScope scope(isolate);
424       return scope.Close(MyObject::NewInstance(args));
425     }
426
427     void InitAll(Handle<Object> exports, Handle<Object> module) {
428       MyObject::Init();
429
430       module->Set(String::NewSymbol("exports"),
431           FunctionTemplate::New(CreateObject)->GetFunction());
432     }
433
434     NODE_MODULE(addon, InitAll)
435
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):
438
439     #define BUILDING_NODE_EXTENSION
440     #ifndef MYOBJECT_H
441     #define MYOBJECT_H
442
443     #include <node.h>
444
445     class MyObject : public node::ObjectWrap {
446      public:
447       static void Init();
448       static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);
449
450      private:
451       MyObject();
452       ~MyObject();
453
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);
457       double counter_;
458     };
459
460     #endif
461
462 The implementation is similar to the above in `myobject.cc`:
463
464     #define BUILDING_NODE_EXTENSION
465     #include <node.h>
466     #include "myobject.h"
467
468     Isolate* isolate = Isolate::GetCurrent();
469
470     using namespace v8;
471
472     MyObject::MyObject() {};
473     MyObject::~MyObject() {};
474
475     Persistent<Function> MyObject::constructor;
476
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);
482       // Prototype
483       tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"),
484           FunctionTemplate::New(PlusOne)->GetFunction());
485
486       constructor = Persistent<Function>::New(isolate, tpl->GetFunction());
487     }
488
489     Handle<Value> MyObject::New(const Arguments& args) {
490       HandleScope scope(isolate);
491
492       MyObject* obj = new MyObject();
493       obj->counter_ = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
494       obj->Wrap(args.This());
495
496       return args.This();
497     }
498
499     Handle<Value> MyObject::NewInstance(const Arguments& args) {
500       HandleScope scope(isolate);
501
502       const unsigned argc = 1;
503       Handle<Value> argv[argc] = { args[0] };
504       Local<Object> instance = constructor->NewInstance(argc, argv);
505
506       return scope.Close(instance);
507     }
508
509     Handle<Value> MyObject::PlusOne(const Arguments& args) {
510       HandleScope scope(isolate);
511
512       MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());
513       obj->counter_ += 1;
514
515       return scope.Close(Number::New(obj->counter_));
516     }
517
518 Test it with:
519
520     var createObject = require('./build/Release/addon');
521
522     var obj = createObject(10);
523     console.log( obj.plusOne() ); // 11
524     console.log( obj.plusOne() ); // 12
525     console.log( obj.plusOne() ); // 13
526
527     var obj2 = createObject(20);
528     console.log( obj2.plusOne() ); // 21
529     console.log( obj2.plusOne() ); // 22
530     console.log( obj2.plusOne() ); // 23
531
532
533 ### Passing wrapped objects around
534
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
538 `MyObject` objects:
539
540     #define BUILDING_NODE_EXTENSION
541     #include <node.h>
542     #include "myobject.h"
543
544     Isolate* isolate = Isolate::GetCurrent();
545
546     using namespace v8;
547
548     Handle<Value> CreateObject(const Arguments& args) {
549       HandleScope scope(isolate);
550       return scope.Close(MyObject::NewInstance(args));
551     }
552
553     Handle<Value> Add(const Arguments& args) {
554       HandleScope scope(isolate);
555
556       MyObject* obj1 = node::ObjectWrap::Unwrap<MyObject>(
557           args[0]->ToObject());
558       MyObject* obj2 = node::ObjectWrap::Unwrap<MyObject>(
559           args[1]->ToObject());
560
561       double sum = obj1->Val() + obj2->Val();
562       return scope.Close(Number::New(sum));
563     }
564
565     void InitAll(Handle<Object> exports) {
566       MyObject::Init();
567
568       exports->Set(String::NewSymbol("createObject"),
569           FunctionTemplate::New(CreateObject)->GetFunction());
570
571       exports->Set(String::NewSymbol("add"),
572           FunctionTemplate::New(Add)->GetFunction());
573     }
574
575     NODE_MODULE(addon, InitAll)
576
577 To make things interesting we introduce a public method in `myobject.h` so we
578 can probe private values after unwrapping the object:
579
580     #define BUILDING_NODE_EXTENSION
581     #ifndef MYOBJECT_H
582     #define MYOBJECT_H
583
584     #include <node.h>
585
586     class MyObject : public node::ObjectWrap {
587      public:
588       static void Init();
589       static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);
590       double Val() const { return val_; }
591
592      private:
593       MyObject();
594       ~MyObject();
595
596       static v8::Persistent<v8::Function> constructor;
597       static v8::Handle<v8::Value> New(const v8::Arguments& args);
598       double val_;
599     };
600
601     #endif
602
603 The implementation of `myobject.cc` is similar as before:
604
605     #define BUILDING_NODE_EXTENSION
606     #include <node.h>
607     #include "myobject.h"
608
609     Isolate* isolate = Isolate::GetCurrent();
610
611     using namespace v8;
612
613     MyObject::MyObject() {};
614     MyObject::~MyObject() {};
615
616     Persistent<Function> MyObject::constructor;
617
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);
623
624       constructor = Persistent<Function>::New(tpl->GetFunction());
625     }
626
627     Handle<Value> MyObject::New(const Arguments& args) {
628       HandleScope scope(isolate);
629
630       MyObject* obj = new MyObject();
631       obj->val_ = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
632       obj->Wrap(args.This());
633
634       return args.This();
635     }
636
637     Handle<Value> MyObject::NewInstance(const Arguments& args) {
638       HandleScope scope(isolate);
639
640       const unsigned argc = 1;
641       Handle<Value> argv[argc] = { args[0] };
642       Local<Object> instance = constructor->NewInstance(argc, argv);
643
644       return scope.Close(instance);
645     }
646
647 Test it with:
648
649     var addon = require('./build/Release/addon');
650
651     var obj1 = addon.createObject(10);
652     var obj2 = addon.createObject(20);
653     var result = addon.add(obj1, obj2);
654
655     console.log(result); // 30