2010-07-03 17 views
7

मैं निम्नलिखित वर्ग है:वी 8 FunctionTemplate कक्षा उदाहरण

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

मैं रजिस्टर विधि जावास्क्रिप्ट से सुलभ होना चाहता हूँ। मैं इस तरह वैश्विक वस्तु में जोड़ें:

PluginManager pluginManagerInstance; 

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

यह निम्न त्रुटि फेंकता है:

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

मैं ऐसा करने की कोशिश की है, लेकिन यह या तो काम नहीं करता। और यह सही नहीं है, क्योंकि मैं इसे प्लगइन प्रबंधक पंजीकरण की रजिस्टर विधि को कॉल करना चाहता हूं।

पंजीकरण विधि स्थिर या वैश्विक बनाने के अलावा, कोई विचार?

धन्यवाद।

उत्तर

5

आप दो चीजों को एक बार में बांधने की कोशिश कर रहे हैं: उदाहरण और उस पर आने का तरीका, और यह एक फ़ंक्शन पॉइंटर जैसा दिखता है। दुर्भाग्यवश वह C++ में काम नहीं करता है। आप केवल एक सादे फ़ंक्शन या स्थिर विधि में पॉइंटर को बाध्य कर सकते हैं। तो छवि आप एक स्थिर "RegisterCB" विधि जोड़कर उसे कॉलबैक के रूप में यह रजिस्टर:

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

अब तुम कहाँ से pluginManagerInstance मिलता है? इस उद्देश्य के लिए, वी 8 में अधिकांश कॉलबैक-पंजीकरण एपीआई में एक अतिरिक्त "डेटा" पैरामीटर होता है जो कॉलबैक पर वापस भेज दिया जाएगा। तो FunctionTemplate :: नया करता है। तो आप वास्तव में इस तरह यह बाध्य करने के लिए चाहते हैं:

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

डेटा) args.Data (के माध्यम से तो उपलब्ध है और आप वास्तविक विधि प्रतिनिधि कर सकते हैं:

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

यह निश्चित रूप से किया जा सकता है एक कुछ मैक्रो के साथ थोड़ा आसान है।

2

आपको इसे स्थिर बनाने की आवश्यकता होगी। सदस्य कार्यों को भूलें इस पैरामीटर को पहले तर्क के रूप में छुपाएं। इस वजह से, वे शायद ही कभी फंक्शन पॉइंटर प्रोटोटाइप के रूप में अच्छी तरह से काम करते हैं।

0

आप कॉल कि विधि के लिए चाहते हैं, तो आप कोष्ठकों जोड़ने के लिए:

:

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

यदि आप चाहते हैं कि इसका पता ले, तो आप एक & जोड़ने के लिए

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

(जो वास्तव में त्रुटि संदेश कहता है।)

+0

इस के बाद से नीचे मतदान किया था, वहाँ कुछ इस के साथ गलत हो रहा है। इसमें ग़लत क्या है? – sbi

2

उदाहरण के लिए this tutorial में कोड को देखें। उपरोक्त सुझाव देता है कि उपरोक्त सुझाव लॉग इन फ़ंक्शन पर इस ऑब्जेक्ट को पॉइंटर भेजने के लिए उपयोग किया जाता है।

शीर्षक में

:

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; 
    } 

कार्यान्वयन:

//////////////////////////////////////////////////////////////////////// 
// 
// 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(); 
} 
+0

धन्यवाद, इससे मुझे बहुत मदद मिली। – danijar

संबंधित मुद्दे