A common practice for emitting events from the Node.js C ++ add-ons module is to port the C ++ component using the javascript component and send them together as a single module. The javascript component passes the callback to the C ++ component. When a C ++ component receives an event, it should call a javascript callback, which in turn should use the EventEmitter to emit .
If you want to see an example of this in practice, I do this in my node-dvbtee module module: http://github.com/mkrufky/node-dvbtee
The source of C ++ add-ons is built from the src/ directory.
The javascript shell can be found in the lib/ directory.
Browse lib/parser.js to find where the listenTables function listenTables called with the callback function as a parameter. Depending on the options module configured, this callback will either call self.push() (for streaming) or self.emit() to generate an event.
To avoid rotting links, a javascript example looks like this:
var _Dvbtee = require('bindings')('dvbtee.node') var util = require('util') var stream = require('stream') var Parser = function (options) { var self = this if (!(this instanceof Parser)) { return new Parser(options) } self.options = {} if (typeof options === 'object') { self.options.passThru = (options.hasOwnProperty('passThru') && options.passThru) } else { self.options.passThru = false } var _parser = new _Dvbtee.Parser var _listenTables = _Dvbtee.Parser.prototype.listenTables var listenTables = _listenTables.bind(_parser) stream.Transform.call(this, { objectMode: !self.options.passThru }) self._buffer = new Buffer(0) listenTables(function(a,b,c) {
The C ++ addon component will have to store the provided callback function in a constant descriptor. NAN provides the perfect structure for this: Nan::Callback
The code for the addon C ++ component should look something like this:
void dvbteeParser::listenTables(const Nan::FunctionCallbackInfo<v8::Value>& info) { dvbteeParser* obj = ObjectWrap::Unwrap<dvbteeParser>(info.Holder()); int lastArg = info.Length() - 1; if ((lastArg >= 0) && (info[lastArg]->IsFunction())) { obj->m_tableReceiver.subscribe(info[lastArg].As<v8::Function>()); } info.GetReturnValue().Set(info.Holder()); }
...
void TableReceiver::subscribe(const v8::Local<v8::Function> &fn) { m_cb.SetFunction(fn); }
... where m_cb is Nan::Callback inside my TableReceiver class. You can indeed call this callback in your own addon event-generation function as follows:
v8::Local<v8::Value> argv[] = { a, b, c }; m_cb.Call(3, argv);
where a, b and c are of type v8::Local<v8::Value> . Of course, the argv array can be of any size. Each element corresponds to the argument provided to this callback function.