2

我在我的 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));

并将对象分配给构造函数中的回调目标。

BattleScreen::callbacktarget = this;

问题是我无法知道我在任何时候都会有多少这样的课程(它会是最小的,但可能大于 1)。我考虑让 callbacktarget 成为 BattleScreen* 的向量,我可以在 TopLevelHandleWebViewCallbacks 中迭代并像这样进行比较:

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

但这里的问题是我只是在比较 awe_webview 指针,这似乎是一个非常糟糕的主意。该库是封闭源代码,awe_webview 是 C 结构,所以我看不出它们是由什么组成的,以及是否有任何属性可以进行更合适的比较。有没有好的解决方案?

如果我不清楚或者您需要更多信息,请告诉我。

提前致谢

4

2 回答 2

2

三种解决方案:

  1. 验证该库是否允许您将任意“上下文”指针绑定到每个awe_webview. 他们通常会这样做。如果是这样,则将指针存储在那里BattleScreen,当调用静态回调时,this从“上下文”中检索指针webview并在此指针上调用成员函数。

  2. 使用全局map<awe_webview*, BattleScreen*>. 在静态回调中,找到BattleScreen对应的webview. 需要锁定全局地图,不漂亮。

    注意:使用指向 webview 的指针作为唯一 id 几乎可以肯定。它总是独一无二的。

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

于 2011-08-14T08:05:45.647 回答
2

回调接收到 awe_webview 指针的事实或多或少证明了比较它们是他们期望你做的。

但是,我会修改您的解决方案以使用 webviews 到 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);

您正在使用的库似乎不是很好:) 您可能希望将其开发人员指向这一点。

于 2011-08-14T08:08:56.857 回答