2012-03-16 17 views
7

私はC言語インターフェイスを使用してDLLを作成するVisual Studio 2008 C++プロジェクトを持っています。コールバック関数には、通常のデータと追加のデータを提供する拡張データの2種類があります。DLLハンドルクラスをスライスします

struct Foo { 
    char a[ MAX_A ]; 
    char b[ MAX_B ]; 
    char c[ MAX_C ]; 
}; 
struct FooEx { 
    char a[ MAX_A ]; 
    char b[ MAX_B ]; 
    char c[ MAX_C ]; 
    char d[ MAX_D ]; 
}; 
typedef void (CALLBACK *USERCALLBACK)(const Foo&, DWORD); 
typedef void (CALLBACK *USERCALLBACK_EX)(const FooEx&, DWORD); 

私はUserData構造の状態を維持します。私はコールバックの2種類がありますので、私は2つの構造で終わる:

struct UserData { 
    DWORD user; 
    int zoo; 
    std::string bar; 
    USERCALLBACK callback; 
}; 

struct UserDataEx { 
    DWORD user; 
    int zoo; 
    std::string bar; 
    USERCALLBACK_EX callback; 
}; 

どのように私はすべての関数の別のEXバージョンを作成せずに、二つの異なるUserData構造を持つ私のAPIを調整できますか?コールバックをテンプレート化する方法はありますか?または、ユーザーデータの基本クラスを作成しますか?

DECLARE_HANDLE(HMYAPI); 

// this function is agnostic of the callback type 
MY_API HMYAPI MyAPI_Create() 
{ 
    return (HMYAPI)new UserData(); 
} 

// This function does not directly use the callback type, but may need to know it to properly deallocate the UserData structure. 
MY_API void MyAPI_Close(HMYAPI handle) 
{ 
    delete reinterpret_cast< UserData* >(handle); 
} 

// this function needs to know about the different callback types 
MY_API void MyAPI_Register(HMYAPI handle, USERCALLBACK cb, DWORD user) 
{ 
    UserData* ud = reinterpret_cast< UserData* >(handle); 
    ud->cb = cb; 
    ud->user = user 
} 

// this function needs to know about the different callback types 
MY_API void MyAPI_RegisterEX(HMYAPI handle, USERCALLBACK_EX cb, DWORD user) 
{ 
    UserData* ud = reinterpret_cast< UserData* >(handle); 
    ud->cb = cb; 
    ud->user = user 
} 

// this function is agnostic of the callback type 
MY_API void Foo(HMYAPI handle, int x) 
{ 
    UserData* ud = reinterpret_cast< UserData* >(handle); 
    ud->bar = "Foo"; 
    ud->zoo = x; 
} 
+11

http://www.partow.net/programming/templatecallback/index.html#VariableArgumentDerivative – Flot2011

答えて

1

ないエレガントな、それが働くだろう:

  • あなたUserDataUserDataEx構造は、ポインタ型以外の同じです。これらの2つの構造体を1つに結合し、コールバックポインタ型をFARPROCに置き換えます。これらの関数ポインタを設定したり取得したりするときは、前後にキャストする必要があります。
  • また、コールバックを標準バージョンまたは "Ex"バージョンにキャストするかどうかを指定するために、ある種の明示的な型情報を構造体に追加する必要があります。たとえば、flagsフィールドを追加し、USES_EXTENDED_CALLBACKフラグを設定できます。
+0

これはおそらく私がやるべきことだと思います。私は、テンプレートを使ってすてきな洗練されたソリューションを望んでいました。ただし、オブジェクトがインスタンス化された後に型を変更できないため、これが唯一の解決策である可能性があります。 – PaulH

+0

'Foo'と' FooEx'は* value *によって渡されていることに注意してください。アドレスを渡すことで、コールバックを簡単にマージすることができます。 –

+0

@レイモンドチェン - まあまあです。コードを更新しました。 – PaulH

関連する問題