views:

52

answers:

3

I have the following class:

class PluginManager
{
public:
    Handle<Value> Register(const Arguments& args);
    Handle<ObjectTemplate> GetObjectTemplate();
};  

I want the Register method to be accessible from JavaScript. I add it to the global object like this:

PluginManager pluginManagerInstance;

global->Set(String::New("register"), FunctionTemplate::New(pluginManagerInstance.Register)); 

It throws the following error:

'PluginManager::Register': function call missing argument list; use '&PluginManager::Register' to create a pointer to member

I tried to do that, but it doesn't work either. And it's not correct, because I want it to call the Register method of the pluginManagerInstance.

Except for making the Register method static or global, any ideas?

Thanks.

+1  A: 

You will likely need to make it static. Don't forget member functions take a hidden this parameter as the first argument. Because of this, they rarely work well as function pointer prototypes.

DanDan
A: 

If you want to call that method, you have to add parentheses:

lobal->Set( String::New("register")
          , FunctionTemplate::New(pluginManagerInstance.Register()) );
                                                                ^^

If you want to take its address, you have to add a &:

lobal->Set( String::New("register")
          , FunctionTemplate::New(&pluginManagerInstance.Register) );
                                  ^

(Which is exactly what the error message says.)

sbi
Since this was down-voted, there seems to be something wrong with this. What _is_ wrong with it?
sbi
A: 

You're trying to bind two things at once: the instance and the method to invoke on it, and have it look like a function pointer. That unfortunately doesn't work in C++. You can only bind a pointer to a plain function or a static method. So image you add a static "RegisterCB" method and register it as the callback:

static Handle<Value> RegisterCB(const Arguments& args);
...FunctionTemplate::New(&PluginManager::RegisterCB)...

Now where do you get the pluginManagerInstance from? For this purpose, most callback-registration apis in V8 have an additional "data" parameter that will get passed back to the callback. So does FunctionTemplate::New. So you actually want to bind it like this:

...FunctionTemplate::New(&PluginManager::RegisterCB,
                         External::Wrap(pluginManagerInstance))...

The data is then available through args.Data() and you can delegate to the actual method:

return ((PluginManager*)External::Unwrap(args.Data())->Register(args);

This can surely be made a little easier with some macro.

mernst