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.