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

コンストラクターでオブジェクトを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構造であるため、それらを構成するものと、より適切な比較を行うプロパティがあるかどうかを確認できません。これに対する良い解決策はありますか?

不明な点がある場合、または追加情報が必要な場合はお知らせください。

前もって感謝します

4

2 に答える 2

2

3つの解決策:

  1. ライブラリで、任意の「コンテキスト」ポインタをそれぞれにバインドできないことを確認してくださいawe_webview。彼らは通常そうします。含まれている場合は、そこにポインタを格納し、静的コールバックが呼び出されたときに、の「コンテキスト」からポインタをBattleScreen取得して、このポインタのメンバー関数を呼び出します。thiswebview

  2. グローバルを使用しmap<awe_webview*, BattleScreen*>ます。静的コールバックで、にBattleScreen対応するを見つけますwebview。きれいではなく、グローバルマップのロックが必要です。

    注:Webviewへのポインターを一意のIDとして使用することは、ほぼ確実に問題ありません。それは常にユニークです。

  3. サンクを使用します(例: http: //www.codeproject.com/KB/cpp/thunk32.aspx)。

于 2011-08-14T08:05:45.647 に答える
2

コールバックがawe_webviewポインターを多かれ少なかれ受け取るという事実は、それらを比較することがあなたが期待することであることを証明しています。

ただし、WebビューとBattleScreenの間でグローバルマップを使用するようにソリューションを変更します。

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

次に、BattleScreenオブジェクトを選択してそのメソッドを呼び出すグローバルコールバックを1つ用意します。

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 に答える