Node.js addon class member functions

The code to expose a static member function of a C++ class in the javascript object looks something like this

tpl->InstanceTemplate()->Set( String::NewSymbol("thefunc"), FunctionTemplate::New(myclass::myfunc)->GetFunction() );

Where thefunc is the name of the function accessible from javascript that maps to the static member myfunc of the class myclass.

Since the method is static we have to access all class instance members via some instance pointer and write some boilerplate code to get at it. For example:

static Handle<Value> myclass::myfunc( const Arguments &args )
{
    myclass *instance = Unwrap<myclass>( args.This() );
    // now use 'instance' like 'this'
    return True();
}

I want to know if it's possible to set a member function in the interface and bind it to the class instance to avoid static functions with boilerplate and have the system call directly into my non-static method so I can use the 'this' pointer.

I can think of a ugly way that involves #define expanding to a template class containing a proxy function that unwraps 'this' and forwards all calls to the member function, which would result in setup code similar to this:

DECLARE_MEMBER_FUNCTION( thefunc_handle, myclass, myfunc );
tpl->InstanceTemplate()->Set( String::NewSymbol("thefunc"), thefunc_handle );

But it seems likely that Node.js already supports this or that someone has devised a better solution.

By introducing a static function template, you can gracefully bind member methods:

class myclass : public node::ObjectWrap
{
    ...

    typedef v8::Handle<v8::Value> (myclass::*WrappedMethod)(const v8::Arguments& args);

    template<WrappedMethod m>
    static v8::Handle<v8::Value> Method(const v8::Arguments& args)
    {
        myclass* obj = ObjectWrap::Unwrap<myclass>(args.This());
        return (obj->*m)(args);
    }

    // Non-static member methods to be exported
    v8::Handle<v8::Value> func1(const v8::Arguments& args);
    v8::Handle<v8::Value> func2(const v8::Arguments& args);
    v8::Handle<v8::Value> func3(const v8::Arguments& args);
};

In you myclass::Init(Handle<Object> exports):

tpl->PrototypeTemplate()->Set(String::NewSymbol("func1"),
    FunctionTemplate::New(Method<&myclass::func1>)->GetFunction());
tpl->PrototypeTemplate()->Set(String::NewSymbol("func2"),
    FunctionTemplate::New(Method<&myclass::func2>)->GetFunction());
tpl->PrototypeTemplate()->Set(String::NewSymbol("func3"),
    FunctionTemplate::New(Method<&myclass::func3>)->GetFunction());

It seems to me that there is no way to use non-static methods instead of static ones. And there two facts exist that may serve as arguments of this:

  • all code samples that you can find in node.js documentation promote using of static functions, so developers aren't imply another use of their library (actually I've never met any other approaches)

  • since node.js callback functions are declared with 'static' modifier you essentially need some class instance to call any instance method. Traditional way is to get the instance from 'Arguments'. You may also use some 'static' pointer to instance you passed to js code, but it works only for one instance. If you want to create more you won't be able to distinguish them when callback is invoked (of course if you don't use some more sophisticated tricks).

To summarize, use of non-static function is rather impossible, since there are no both simple and legitimate technics to operate them