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:
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 toBattleScreenand when the static callback is called, retrievethispointer from the 'context' ofwebviewand call the member function on this pointer.Use a global
map<awe_webview*, BattleScreen*>. In the static callback, find theBattleScreencorresponding to thewebview. 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.
Use thunks (e.g. http://www.codeproject.com/KB/cpp/thunk32.aspx).
加载中,请稍侯......
精彩评论