2012-03-16 54 views
7

我有一個Visual Studio 2008 C++項目,我用C接口創建一個DLL。我定義了兩種類型的回調函數:常規函數和擴展函數提供附加數據。切片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結構維護狀態。因爲我有兩個類型的回調,我結束了兩種結構:

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

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

如何調和我的API具有兩種不同UserData結構,而無需創建每個功能的獨立EX版本?有沒有一種方法來模擬回調?或者創建一個基類的用戶數據?

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 2012-03-16 20:39:32

回答

1

不優雅,但它的工作:

  • UserDataUserDataEx結構比指針類型相同等。將這兩個結構合併爲一個,並用FARPROC替換回調指針類型。設置和檢索這些函數指針時,必須來回轉換。
  • 您還需要在結構中添加某種顯式類型信息,以指定是否將回調強制轉換爲標準版本或「Ex」版本。例如,您可以添加一個flags字段並設置一個USES_EXTENDED_CALLBACK標誌。
+0

我認爲這可能是我必須要做的。我希望有一個很好的優雅的模板解決方案。但是,這可能是唯一的解決方案,因爲在實例化對象之後無法更改類型。 – PaulH 2012-03-16 21:31:25

+0

請注意'Foo'和'FooEx'正在被* value *傳遞。通過地址傳遞它們可以更容易地合併回調。 – 2012-03-16 22:07:24

+0

@RaymondChen - 很對。我更新了代碼。 – PaulH 2012-03-17 01:58:39