2010-07-03 3 views
7

나는 다음 클래스가 있습니다V8 FunctionTemplate 클래스 인스턴스

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

내가 등록 방법은 자바 스크립트에서 액세스 할 수하고자합니다.

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

내가 그렇게했지만, 그 중 하나가 작동하지 않습니다

PluginManager pluginManagerInstance; 

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

그것은 다음과 같은 오류가 발생합니다 :이 같은 전역 객체에 추가합니다. 그리고 그것은 정확하지 않습니다. 왜냐하면 나는 pluginManagerInstance의 Register 메소드를 호출하기를 원하기 때문입니다.

Register 메서드를 정적 또는 전역으로 만드는 것을 제외하고는 어떤 아이디어입니까?

감사합니다.

답변

5

두 가지를 즉시 바인딩하려고합니다 : 인스턴스와 그 인스턴스에서 호출하는 메소드가 함수 포인터처럼 보입니다. 불행히도 C++에서는 작동하지 않습니다. 포인터는 일반 함수 또는 정적 메서드에만 바인딩 할 수 있습니다. 그래서 이미지가 정적 "RegisterCB"방법을 추가하고 콜백으로 등록 : 이제

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

당신이에서 pluginManagerInstance을받을 수 있나요? 이를 위해 V8의 대부분의 콜백 등록 api에는 콜백으로 다시 전달되는 추가 'data'매개 변수가 있습니다. 그렇다면 FunctionTemplate :: New도 마찬가지입니다. 그래서 당신은 실제로처럼 바인딩 할 :

...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

이 아래로 뽑혔다이 뭔가 문제가있는 것 같습니다. _is_ 무엇이 잘못 되었습니까? – sbi

2

예를 들어 this tutorial의 코드를 살펴보십시오. 위의 mernst가 제안한 것과 같은 메소드가이 객체에 대한 포인터를 로그 함수로 보내는 데 사용됩니다.헤더

:

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

관련 문제