From f210710795240c646746cb9d9c752d46a026200b Mon Sep 17 00:00:00 2001 From: Rod Vagg Date: Mon, 21 Jan 2013 14:20:43 +1100 Subject: [PATCH] doc: NODE_MODULE() to pass full `module` to addons mainly to allow native addons to export single functions on `exports` rather than being restricted to operating on an existing `exports` object. added link to addons repo in docs --- doc/api/addons.markdown | 66 +++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/doc/api/addons.markdown b/doc/api/addons.markdown index b414943c6a..930c3fe53e 100644 --- a/doc/api/addons.markdown +++ b/doc/api/addons.markdown @@ -23,13 +23,15 @@ Node statically compiles all its dependencies into the executable. When compiling your module, you don't need to worry about linking to any of these libraries. +All of the following examples are available for [download](https://github.com/rvagg/node-addon-examples) +and may be used as a starting-point for your own Addon. ## Hello world To get started let's make a small Addon which is the C++ equivalent of the following JavaScript code: - exports.hello = function() { return 'world'; }; + module.exports.hello = function() { return 'world'; }; First we create a file `hello.cc`: @@ -43,15 +45,16 @@ First we create a file `hello.cc`: return scope.Close(String::New("world")); } - void init(Handle target) { - target->Set(String::NewSymbol("hello"), + void init(Handle exports) { + exports->Set(String::NewSymbol("hello"), FunctionTemplate::New(Method)->GetFunction()); } + NODE_MODULE(hello, init) Note that all Node addons must export an initialization function: - void Initialize (Handle target); + void Initialize (Handle exports); NODE_MODULE(module_name, Initialize) There is no semi-colon after `NODE_MODULE` as it's not a function (see `node.h`). @@ -154,8 +157,8 @@ function calls and return a result. This is the main and only needed source return scope.Close(num); } - void Init(Handle target) { - target->Set(String::NewSymbol("add"), + void Init(Handle exports) { + exports->Set(String::NewSymbol("add"), FunctionTemplate::New(Add)->GetFunction()); } @@ -189,18 +192,23 @@ there. Here's `addon.cc`: return scope.Close(Undefined()); } - void Init(Handle target) { - target->Set(String::NewSymbol("runCallback"), + void Init(Handle exports, Handle module) { + module->Set(String::NewSymbol("exports"), FunctionTemplate::New(RunCallback)->GetFunction()); } NODE_MODULE(addon, Init) +Note that this example uses a two-argument form of `Init()` that receives +the full `module` object as the second argument. This allows the addon +to completely overwrite `exports` with a single function instead of +adding the function as a property of `exports`. + To test it run the following JavaScript snippet: var addon = require('./build/Release/addon'); - addon.runCallback(function(msg){ + addon(function(msg){ console.log(msg); // 'hello world' }); @@ -225,8 +233,8 @@ the string passed to `createObject()`: return scope.Close(obj); } - void Init(Handle target) { - target->Set(String::NewSymbol("createObject"), + void Init(Handle exports, Handle module) { + module->Set(String::NewSymbol("exports"), FunctionTemplate::New(CreateObject)->GetFunction()); } @@ -236,8 +244,8 @@ To test it in JavaScript: var addon = require('./build/Release/addon'); - var obj1 = addon.createObject('hello'); - var obj2 = addon.createObject('world'); + var obj1 = addon('hello'); + var obj2 = addon('world'); console.log(obj1.msg+' '+obj2.msg); // 'hello world' @@ -266,8 +274,8 @@ wraps a C++ function: return scope.Close(fn); } - void Init(Handle target) { - target->Set(String::NewSymbol("createFunction"), + void Init(Handle exports, Handle module) { + module->Set(String::NewSymbol("exports"), FunctionTemplate::New(CreateFunction)->GetFunction()); } @@ -278,7 +286,7 @@ To test: var addon = require('./build/Release/addon'); - var fn = addon.createFunction(); + var fn = addon(); console.log(fn()); // 'hello world' @@ -294,8 +302,8 @@ module `addon.cc`: using namespace v8; - void InitAll(Handle target) { - MyObject::Init(target); + void InitAll(Handle exports) { + MyObject::Init(exports); } NODE_MODULE(addon, InitAll) @@ -309,7 +317,7 @@ Then in `myobject.h` make your wrapper inherit from `node::ObjectWrap`: class MyObject : public node::ObjectWrap { public: - static void Init(v8::Handle target); + static void Init(v8::Handle exports); private: MyObject(); @@ -335,7 +343,7 @@ prototype: MyObject::MyObject() {}; MyObject::~MyObject() {}; - void MyObject::Init(Handle target) { + void MyObject::Init(Handle exports) { // Prepare constructor template Local tpl = FunctionTemplate::New(New); tpl->SetClassName(String::NewSymbol("MyObject")); @@ -345,7 +353,7 @@ prototype: FunctionTemplate::New(PlusOne)->GetFunction()); Persistent constructor = Persistent::New(tpl->GetFunction()); - target->Set(String::NewSymbol("MyObject"), constructor); + exports->Set(String::NewSymbol("MyObject"), constructor); } Handle MyObject::New(const Arguments& args) { @@ -399,10 +407,10 @@ Let's register our `createObject` method in `addon.cc`: return scope.Close(MyObject::NewInstance(args)); } - void InitAll(Handle target) { + void InitAll(Handle exports, Handle module) { MyObject::Init(); - target->Set(String::NewSymbol("createObject"), + module->Set(String::NewSymbol("exports"), FunctionTemplate::New(CreateObject)->GetFunction()); } @@ -490,14 +498,14 @@ The implementation is similar to the above in `myobject.cc`: Test it with: - var addon = require('./build/Release/addon'); + var createObject = require('./build/Release/addon'); - var obj = addon.createObject(10); + var obj = createObject(10); console.log( obj.plusOne() ); // 11 console.log( obj.plusOne() ); // 12 console.log( obj.plusOne() ); // 13 - var obj2 = addon.createObject(20); + var obj2 = createObject(20); console.log( obj2.plusOne() ); // 21 console.log( obj2.plusOne() ); // 22 console.log( obj2.plusOne() ); // 23 @@ -533,13 +541,13 @@ In the following `addon.cc` we introduce a function `add()` that can take on two return scope.Close(Number::New(sum)); } - void InitAll(Handle target) { + void InitAll(Handle exports) { MyObject::Init(); - target->Set(String::NewSymbol("createObject"), + exports->Set(String::NewSymbol("createObject"), FunctionTemplate::New(CreateObject)->GetFunction()); - target->Set(String::NewSymbol("add"), + exports->Set(String::NewSymbol("add"), FunctionTemplate::New(Add)->GetFunction()); }