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)。我考虑将回调目标设置为 BattleScreen* 的向量,我可以在 TopLevelHandleWebViewCallbacks 内部进行迭代并像这样进行比较:
if (callbacktargets[index]->GetWebview() == WebView)
{
callbacktargets[index]->HandleWebviewCallbacks(WebView, object, callback, arguments);
}
但这里的问题是我只比较 awe_webview 指针,这似乎是一个非常糟糕的主意。该库是闭源的,awe_webview 是 C 构造,因此我看不到它们的组成部分以及是否有任何属性可以进行更合适的比较。对此有好的解决办法吗?
如果我不清楚或者您需要更多信息,请告诉我。
提前致谢
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 comparison. Is there a good solution to this?
If I'm being unclear or you need additional information let me know.
Thanks in advance
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
回调接收 awe_webview 指针的事实或多或少证明了比较它们是它们期望您做的事情。
但是,我会修改您的解决方案,以在 webview 到 BattleScreens 之间使用全局映射:
然后有一个全局回调,从中选取 BattleScreen 对象并调用其方法:
好的库允许您通过回调传递上下文指针,因此您可以将诸如 BattleObject* 之类的内容分配给您设置的每个回调:
您正在使用的库似乎不太好:)您可能希望向其开发人员指出这一点。
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:
Then have one global callback that picks the BattleScreen object from it and calls its method:
Nice libraries allow you to pass a context pointer with the callback, so you can assign something like BattleObject* to each callback you set:
The library you are using does not seem to be very nice :) You may want to point its developers to this.
三个解决方案:
验证库不允许您将任意“上下文”指针绑定到每个
awe_webview
。他们通常会这样做。如果是,则将指向BattleScreen
的指针存储在那里,并在调用静态回调时,从webview
的“上下文”中检索this
指针,并调用此指针上的成员函数。使用全球
地图
。在静态回调中,找到webview
对应的BattleScreen
。需要锁定全局地图,不太漂亮。注意:使用指向 webview 的指针作为唯一 id 几乎肯定是可以的。它始终是独一无二的。
使用thunk(例如http://www.codeproject.com/KB/cpp/ thunk32.aspx)。
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 toBattleScreen
and when the static callback is called, retrievethis
pointer from the 'context' ofwebview
and call the member function on this pointer.Use a global
map<awe_webview*, BattleScreen*>
. In the static callback, find theBattleScreen
corresponding 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).