2011-08-14 131 views
2

我在我的C++應用程序中使用C庫。圖書館擁有具有以下簽名的函數:函數指針的C++對象函數

void awe_webview_set_callback_js_callback(awe_webview* webview, void (*callback)(awe_webview* caller, const awe_string* object_name, const awe_string* callback_name, const awe_jsarray* arguments)); 

我正在嘗試設置一個函數作爲一個回調,我想可以使用下面的類成員函數

void BattleScreen::HandleWebViewCallbacks(awe_webview* WebView, const awe_string* object, const awe_string* callback, const awe_jsarray* arguments) 
{ 
    //handling code 
} 

我不能直接綁定它並基於這裏http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.2我有一個可能的解決方案,我將創建一個靜態成員來處理回調(因爲基於該網站,它應該沒問題)並添加此類的靜態實例供靜態成員調用。

即以下添加到BattleScreen:

static BattleScreen* callbacktarget; 
static BattleScreen::TopLevelHandleWebViewCallbacks(awe_webview* WebView, const awe_string* object, const awe_string* callback, const awe_jsarray* arguments) 
{ 
     callbacktarget->HandleWebviewCallbacks(WebView, object, callback, arguments); 
} 

將其綁定在構造像這樣:

awe_webview_set_callback_js_callback(this->GetWebView(), static_cast<void (*)(awe_webview*, const awe_string*, const awe_string*, const awe_jsarray*)>(&BattleScreen::TopLevelHandleWebViewCallbacks)); 

並分配在構造函數中callbacktarget的對象。

BattleScreen::callbacktarget = this; 

的問題是我不知道我有多少這些類將有在任何一個時間的方式(這將是最小的,但有可能大於1)。我認爲使callbacktarget BattleScreen *的載體,我可以通過內部TopLevelHandleWebViewCallbacks迭代和比較像這樣:

if (callbacktargets[index]->GetWebview() == WebView) 
{ 
    callbacktargets[index]->HandleWebviewCallbacks(WebView, object, callback, arguments); 
} 

但這裏的問題是,我只是比較awe_webview指針這似乎是一個非常糟糕的主意。該庫是封閉的源代碼,而awe_webview是C構造,所以我不能看出是什麼使它們變成了現實,以及是否有任何屬性可以做出更合適的比較。有沒有一個很好的解決方案?

如果我不清楚或者需要更多信息,請告訴我。

在此先感謝

回答

2

回調接收awe_webview指針或多或少的事實證明,比較它們是他們希望你做的事情。

不過,我想修改您的解決方案使用BattleScreens網頁視圖之間的全球地圖:

static std::map<awe_webview*, BattleScreen*> gWebViewBattleScreen; 

然後有一個全球性的回調,從它挑選BattleScreen對象,並調用其方法:

static void webviewCallback(awe_webview* caller, ......) 
{ 
    if (gWebViewBattleScreen.find(caller) != gWebViewBattleScreen.end()) 
     gWebViewBattleScreen[caller]->HandleWebViewCallbacks(......) 
} 

尼斯庫允許您將回調指針傳遞給回調函數,因此您可以爲您設置的每個回調指定類似BattleObject *的東西:

void set_nice_callback(void (*callback)(Params params, void* context), void* context); 
void set_nice_callback(void (*callback)(Params params, void* context), void* context); 

你正在使用的庫似乎不是很好:)你可能想要指出它的開發人員。

2

三種解決方案:

  1. 驗證庫不允許你隨心所欲的「語境」指針綁定到每個awe_webview。他們通常這樣做。如果存在,則在那裏存儲指向BattleScreen的指針,並在調用靜態回調時,從webview的「上下文」中檢索this指針,並在該指針上調用成員函數。使用全球map<awe_webview*, BattleScreen*>。在靜態回調中,找到對應於webviewBattleScreen。需要鎖定全球地圖,而不是漂亮。

    注意:使用指向webview的指針作爲唯一的ID幾乎肯定可以。它總是獨一無二的。

  2. 使用thunks(例如http://www.codeproject.com/KB/cpp/thunk32.aspx)。