V8 FunctionTemplate Instance

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 am adding it to a global object like this:

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

It produces the following error:

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

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

Except the Register method is static or global, any ideas?

Thanks.

+7
c ++ static v8 instance
source share
4 answers

You are trying to connect two things at once: an instance and a method to call on it and have it as a pointer to a function. This, unfortunately, does not work in C ++. You can only bind a pointer to a simple function or static method. Thus, you add the static method "RegisterCB" and register it as a callback:

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

Now where do you get pluginManagerInstance? For this purpose, most apis callback registrations in V8 have an additional β€œdata” parameter that will be passed back to the callback. Also FunctionTemplate :: New. So you really want to link it like this:

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

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

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

It might be a little easier with some macros.

+5
source share

You probably need to make it static. Remember that member functions accept this parameter as their first argument. Because of this, they rarely work well, like prototypes of function pointers.

+2
source share

As an example, consider the code for this tutorial . The same mernst method proposed above is used to send a pointer to this object, to the log function.

in the title:

  virtual void log(const string &str); static Handle<Value> logCallback(const Arguments &args); Local<FunctionTemplate> makeStaticCallableFunc(InvocationCallback func); Local<External> classPtrToExternal(); //////////////////////////////////////////////////////////////////////// // // Converts an External to a V8TutorialBase pointer. This assumes that the // data inside the v8::External is a "this" pointer that was wrapped by // makeStaticCallableFunc // // \parameter data Shoudld be v8::Arguments::Data() // // \return "this" pointer inside v8::Arguments::Data() on success, NULL otherwise // //////////////////////////////////////////////////////////////////////// template <typename T> static T *externalToClassPtr(Local<Value> data) { if(data.IsEmpty()) cout<<"Data empty"<<endl; else if(!data->IsExternal()) cout<<"Data not external"<<endl; else return static_cast<T *>(External::Unwrap(data)); //If function gets here, one of the checks above failed return NULL; } 

implementation:

 //////////////////////////////////////////////////////////////////////// // // Wrap a callback function into a FunctionTemplate, providing the "this" // pointer to the callback when v8 calls the callback func // // \parameter func Static callback to be used in FunctionTemplate // // \return Local<FunctionTemplate> containing func // //////////////////////////////////////////////////////////////////////// Local<FunctionTemplate> V8TutorialBase::makeStaticCallableFunc(InvocationCallback func) { HandleScope scope; Local<FunctionTemplate> funcTemplate = FunctionTemplate::New(func, classPtrToExternal()); return scope.Close(funcTemplate); } //////////////////////////////////////////////////////////////////////// // // Makes the "this" pointer be an external so that it can be accessed by // the static callback functions // // \return Local<External> containing the "this" pointer //////////////////////////////////////////////////////////////////////// Local<External> V8TutorialBase::classPtrToExternal() { HandleScope scope; return scope.Close(External::New(reinterpret_cast<void *>(this))); } Handle<Value> V8TutorialBase::logCallback(const Arguments &args) { HandleScope scope; ..... V8TutorialBase *objPtr = externalToClassPtr<V8TutorialBase>(args.Data()); String::Utf8Value val(Local<String>::Cast(args[0])); objPtr->log(*val); // log is a non static member function // or you can directly do anything that you would do in a member function using the objPtr return v8::Null(); } 
+2
source share

If you want to call this method, you need to add parentheses:

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

If you want to take your address , you must add & :

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

(This is exactly what the error message says.)

0
source share

All Articles