开发者

C++ object function to function pointer

I'm using a C library inside my C++ app. The library has a function with the following signature:

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

I'm trying to set a function as a call back and I'd like to be able to use the following class member function

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

I can't bind it directly and based on here http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.2 I have a possible solution where I'd create a static member to handle the callback (since based on that site, it should be fine) and add a static instance of this class for the static member to call on.

i.e. add the following to 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);
}

bind it in the constructor like so:

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

and assign the object to callbacktarget in the constructor.

BattleScreen::callbacktarget = this;

The problem is I have no way of knowing how many of these classes I will have at any one time (It'll be minimal but possibly greater then 1). I considered making the callbacktarget a vector of BattleScreen* that i can iterate through inside TopLevelHandleWebViewCallbacks and compare like so:

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

but the problem here is that I'm only comparing the awe_webview pointers which seems like a really bad idea. The library is closed source and the awe_webview's are C constructs so I can't see what makes them up and if there are any properties that would make a more suitable compari开发者_高级运维son. Is there a good solution to this?

If I'm being unclear or you need additional information let me know.

Thanks in advance


The fact that callbacks receive awe_webview pointer more or less proves that comparing them is what they expect you to do.

However, I would modify your solution to use a global map between webviews to BattleScreens:

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

Then have one global callback that picks the BattleScreen object from it and calls its method:

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

Nice libraries allow you to pass a context pointer with the callback, so you can assign something like BattleObject* to each callback you set:

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

The library you are using does not seem to be very nice :) You may want to point its developers to this.


Three solution:

  1. Verify that the library doesn't allow you to bind arbitrary 'context' pointer to each awe_webview. They usually do. If it does, store there the pointer to BattleScreen and when the static callback is called, retrieve this pointer from the 'context' of webview and call the member function on this pointer.

  2. Use a global map<awe_webview*, BattleScreen*>. In the static callback, find the BattleScreen corresponding to the webview. Requires locking of the global map, not pretty.

    Note: using a pointer to webview as a unique id is almost surely OK. It's always unique.

  3. Use thunks (e.g. http://www.codeproject.com/KB/cpp/thunk32.aspx).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜