2010-11-24 2 views
2

私は新しい分野に入っていますが、基本的にC++でコールバックを実装する必要があります。私は自分の人生を単純化するために使うツールキットを設計しています。基本的には、他の.dllプラグインに多くの機能を公開する.dllプラグインです。C++コールバック?メンバー関数ポインタ/代理人/イベントを使用する必要がありますか?

これらの関数の1つは、HookEvent(const char * event_name、void * callback)です。これにより、発生するさまざまなイベントをフックできます。ここに例があります...

Example_Plugin1.dllはHookEvent( "player_spawn"、& Plugin1 :: Event_PlayerSpawn)です。 Example_Plugin2.dllはHookEventを実行します( "player_spawn"、& Plugin2 :: Event_PlayerSpawn)。

これでうまくいくコールバックシステムを設定するには、最良の(そして、できるだけ簡単な)方法を見つけ出す必要があります。私は数時間前からC++コールバックを読んできましたが、かなりのアプローチがありました。

私はテンプレートを作るのが最も簡単なことを想定し、typedef bool(ClassName :: * EventHookCallback)(IGameEvent、bool);を使用します。それから、私はちょっと曇っています。

また、デリゲートや.NETスタイルのイベントシステムが他の方法でも使用できることも読んでいます。私はすでに幾分混乱しているので、もっと自分を混乱させたくはありませんが、質問する価値があると考えました。

私が読んでいたC++ .NETスタイルイベントシステムへのリンクです。 http://cratonica.wordpress.com/2010/02/19/implementing-c-net-events-in-c/

あなたは何をお勧めしますか?それを実装するまでのヒントは、最も高く評価されます。

答えて

3

一般的なイベントの発射を希望する場合は、Boost.Signals2が該当します。

Boost.Signals2ライブラリは、管理信号 及びスロットシステムの 実装です。信号は複数のターゲットを持つ コールバックを表し、 は同様のシステムのパブリッシャーまたはイベント とも呼ばれます。信号は 信号がされたときに呼び出される は(も イベントターゲットまたは加入者とも呼ばれる)コールバック受信機であるスロットのいくつかのセット、に接続されている「放出されました」。

このレベルの柔軟性が必要ない場合でも、Boost.Bindまたは同等のC++ 0xを使用してコード内の関数バインドを単純化することができます。

EDIT: ハーブ・サッターの素晴らしい話題は、hereに直面する可能性のある問題です。 Boostの完全な機能が必要ないと判断した場合は、これを使用して独自のロールを作成することができます。

+0

できるだけBoostや別のライブラリを使用せずにやりたいと思っていました。メンバー関数のポインタや代理人を使用するのとは対照的に、これは本当に簡単でしょうか? –

+1

シンプルなコールバックが必要な場合、これは過剰です。完全なObserverパターンの実装には、これが役に立ちます。コスト/利益の決定は、期待されるニーズに依存します。あなたのコンパイラにC++ 0xを持っていれば、ラムダ(ローカルの無名関数)を '代理人'にすることさえできます。これをチェックしてください:http://uint32t.blogspot.com/2009/05/using-c0x-lambda-to-replace-boost-bind.html –

+0

私は実際にそれが好きですが、私はちょうどこれと一緒に行くつもりだと思います私がこれまで見てきたものの中で私が最も理解しやすいように思えるシステムです。 http://cratonica.wordpress.com/2010/02/19/implementing-c-net-events-in-c/ –

1

Qtシグナルとスロットの使用はどうですか?コールバックが行うことはしますが、コールバックパラメータの一部ではないことを煩雑にすることはありません。

0

独自のプラグインフレームワークの構築方法に興味があるようです。遭遇する問題は同じだろう。この素敵なDr Dobbsの記事Building Your Own Plugin Frameworkを見てください。

希望すると便利です。

+0

それは見た目ほど面白く、私はそれが私のニーズにとって非常に複雑すぎると信じています。私が言及したように、私はすでに他のプラグインにこれ​​らの関数を作成/公開するために.dllプラグインを使用しています。私が使用しているAPIは簡単な方法を提供します。 –

+0

あなたはあなたが必要とするものを知っているように聞こえます。がんばろう! –

1

Boost.Signalsは、boost::bindBoost.Functionのようなものを組み合わせたものです。

0

私は抽象基本クラスをプラグインインタフェースとして使用します。 (そして実際に、私の前に以下のようなパターンを使用しています。)

図書館、PluginIfc.h:

class PluginIfc { 
public: 
    virtual ~PluginIfc() = 0; 
    virtual bool EventCallback(const char* event_name, IGameEvent, bool) = 0;  
}; 

// For Windows, add dllexport/dllimport magic to this declaration. 
// This is the only symbol you will look up from the plugin and invoke. 
extern "C" PluginIfc* GetPlugin(); 

プラグイン:

#include <PluginIfc.h> 
class Plugin1 : public PluginIfc { 
public: 
    virtual bool EventCallback(const char* event_name, IGameEvent, bool); 
    Plugin1& get() { return the_plugin_obj; } 

    bool Event_PlayerSpawn(IGameEvent, bool); 
    // ... 
private: 
    std::vector<std::string> _some_member; 

    static Plugin1 the_plugin_obj; // constructed when plugin loaded 
}; 

Plugin1 Plugin1::the_plugin_obj; 
PluginIfc* GetPlugin() { return &Plugin1::get(); } 

この方法で、あなたのプラグインクラスすることができますメンバを簡単に持つことができ、C++のバーチャルコールメカニズムによって、thisというポインタがEventCallbackに渡されます。

イベントタイプごとに仮想メソッドを作成することができます。たとえば、Event_PlayerSpawnなどの仮想メソッドを仮想化することができます。しかし、イベントタイプを追加したい場合は、クラスPluginIfcを変更することを意味する場合、古いコンパイル済みプラグインはもはや互換性がなくなります。したがって、(拡張性のために)文字列イベント識別子を使用し、メインのコールバックソートイベントをより具体的なメソッドにする方が安全です。

ここでの主な欠点(信号スロット型の実装と比較して)は、すべてのコールバックが同じ引数セットを取る必要があるということです。しかし、あなたの質問はそれが適切であるように聞こえました。また、多くの場合、引数のセットが解析される文字列やAnyスタイルのオブジェクトを使用して非常に柔軟であることを確認することで、その制限内で作業することが可能です。

0

独自のコールバックシステムの実装は簡単です。
私の理解は、イベントタイプを特定のコールバック関数にマップすることです。
など。 「player_spawn」イベントが発生した場合、& Plugin1 :: Event_PlayerSpawnが呼び出されます。
あなたがすべきことは次のとおりです。
1)興味のあるイベントをすべて定義してください。できるだけ包括的にしてください。彼らは 必要な情報をカプセル化することができます
2)レジストラを作成します。私。すべてのモジュールが特定の メソッドに対して関心を登録するクラスです。例えば。 Registrar.register(player_spawn,this,Event_PlayerSpawn);
3) Registrarにはすべてのサブスクライバのキューがあります。
4)また、モジュールの統一されたインターフェイスを持つこともできます。私。すべてのモジュールは、特定の機能を実装しますが、イベントのデータに基づいて異なるものに
5を行うことができます)イベントが発生すると、特定のイベントのために興味を持ってすべての加入者が適切な機能
6を呼び出すことで通知を受ける)加入者が解除することができます登録が必要なときに登録する
これが役立つことを願っています。

関連する問題