Hi!

I am writing node.js bindings for a C library. Some of the C API takes 
callback function pointers, so my corresponding JS API will accept JS 
callbacks. I intend to use a hybrid JS/C++ solution to achieve running the 
JS callback whenever the C callback gets called. Let's say the C API has 
the following signature:

void c_api_function( int flags, void (*callback)() );

Let's further say that the name of my module is cApiBindings (i.e., you 
will load the module by doing require( "bindings" )( "cApiBindings" ) ), 
and that I intend to expose the above function as 
cApiBindings.c_api_function(). I was thinking about achieving this as 
follows:

------------------------------------------------------------------------------------------------------
1. The JS side:
var cApiBindings = require( "bindings" )( "cApiBindings" );

cApiBindings.callbacks = {};

cApiBindings.callbackUuid = 0;

cApiBindings.c_api_function( flags, callback ) {
  var uuid = cApiBindings.callbackUuid++;

  cApiBindings.callbacks[ uuid ] = callback;

  return cApiBindings._partial_c_api_function( flags, uuid );
};

IOW, store the callback in an array of currently active callbacks, and pass 
the location of the JS callback to the C++ side.

2. The C++ side, containing the crux of the problem:

void default_c_api_callback( int uuid ) {
  Local<Function> callback = Local<Function>::Cast(
    ?????->Get( String::NewFromUtf8( "callbacks" ) )
      ->Get( uuid ) );

  /* Execute the JS callback thus retrieved */
}

void bind__partial_c_api_function(  const FunctionCallbackInfo<Value>& args 
) {
  int flags = args[ 0 ]->ToUint32(),
    uuid = args[ 1 ]->ToUint32();

  /* Create a closure using libffi so that uuid ends up getting passed to 
default_c_api_callback() as defined above */
  void (*closure)() = create_closure( default_c_api_callback, uuid );

  c_api_function( flags, closure );
}

void Init( Handle<Object> exports, Handle<Object> module ) {
  NODE_SET_METHOD( exports, "_partial_c_api_function", 
bind__partial_c_api_function );
}

NODE_MODULE( cApiBindings, Init )
------------------------------------------------------------------------------------------------------

As you can see, in the C callback I need a way of retrieving the module 
onto which I've defined all the bindings, and onto which the JS side has 
defined the callbacks hash. Where does node keep this reference? For JS 
modules, it's in a parameter passed into the outermost IIFE, so it's always 
within the scope of the module.

I've tried to simply define a global variable

Handle<Object> module_exports;

and set it inside Init() as

module_exports = exports;

but that is useless, because attempting to access members of module_exports 
from the C callback via module_exports->Get(...) results in a segault. So, 
is there a correct way of storing a reference to module and/or exports that 
gets passed into Init() in a global variable for later use by the C 
callback?

Can I somehow work my way from Isolate::GetCurrent()?

I have successfully assigned the module object to a key on the global 
object inside Init():

Isolate::GetCurrent()->GetCurrentContext()->Global()
  ->ForceSet( String::NewFromUtf8( Isolate::GetCurrent(), "cApiBindings" ), 
module,
    ( PropertyAttribute )( ReadOnly | DontEnum | DontDelete ) );

I can then retrieve the module off the global object later on. Great, but 
I'd rather not pollute the global object. I'd much rather store module in a 
global variable in the source file instead. Is there a correct way of doing 
that?

TIA for your help,



Gabriel

-- 
Job board: http://jobs.nodejs.org/
New group rules: 
https://gist.github.com/othiym23/9886289#file-moderation-policy-md
Old group rules: 
https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
--- 
You received this message because you are subscribed to the Google Groups 
"nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/nodejs/13d48767-2790-4759-924f-fd3338ee135b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to