0

I am wrapping a CAN Bus manager API in a node.js extension. Everything works well, this would be the final result:

// list interfaces
var interfaces = addon.listDevices();
console.log(interfaces);

// Allocating a new port
var port = new addon.CANPort();
port.setCallback(function(msg) {
    // I would like to receive all CAN datagrams
    console.log(msg);
});

// Connect to the 1st port
port.connect(0);
// Send a datagram
port.sendStruct(127508, 6, Array(0, 70, 5, 50, 0, 131, 114, 0));

Every function is OK but the setCallback function. Actually, I don't know what to do. I have a c++ callback of this this type :

void CANPort::SetReceiveCallback(functionCallback func);

which will call the function when it receives a new datagram.

I found in http://nikhilm.github.io/uvbook/threads.html some help, but I can't find the right way to do the same as the last example. I know I should use uv, but I don't know how...

Moreover, I'm using the v0.11.14-pre of Node.js, so a lot of documentation is out of date...

Thanks, Nicolas.

7
  • You cannot do this inline: function(msg) { // I would like to receive all CAN datagrams console.log(msg); } declare the function outside somewhere and call port.setCallback(function); Commented Jun 20, 2014 at 11:15
  • Why is it different ? The type is identical, right ? Maybe a difference between named functions and lambda functions ? Commented Jun 20, 2014 at 11:23
  • 'Why is it different ?' Because that's not valid c++ syntax dude! Even lambda should be declared first IMHO, but you don't have lambda declaration/definition syntax there. Commented Jun 20, 2014 at 11:26
  • what is your functionCallback ? i hope you have written some valid v8 bindings in cpp side; Commented Jun 20, 2014 at 11:27
  • that is not cpp but javascript code :) Commented Jun 20, 2014 at 11:28

1 Answer 1

1

Although this is kind of old, but I used a hybrid javascript/C++ mechanism to integrate external callbacks. Basically call uv_queue_work() in your callback with uv_work_t that performs nothing, and use its after_work_cb to call your javascript function:

// C++

void nop() {}

void jscallback(uv_work_t* handle, int status)
{
  // extract some_data from handle and call node::MakeCallback() here
  // I make it call emit('event', some_data);
  delete handle;
}

void called_by_third_party_callback(some_type some_data)
{
  uv_work_t uv = new uv_work_t();
  if (!uv) {
    // error
  }
  // ensure some_data is accessible via uv->data
  if (uv_queue_work(uv_default_loop(), uv, nop, jscallback) != 0) {
    delete uv;
  }
}

On my javascript side I used a string-to-function map to implement a simple Event Emitter mechanism on top of my Engine object:

// Javascript

exports.Engine.prototype.eventMap = [];
exports.Engine.prototype.on = function (name, func) {
  if (typeof (func) === "function") {
    this.eventMap[name] = func;
}

exports.Engine.prototype.emit = function (name, value) {
  var func = this.eventMap[name];
  if (typeof (func) === "function") {
    func(value);
  }
}

This is how I use it:

// Javascript

var obj = new require('myaddon').Engine();

obj.on('event', function (v) {
  console.log('event: ' + v);
});

Sorry for using comments excessively. My code is too intertwined to be shown as snipplets.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.