2010-06-01 23 views
3

我正想着在類中封裝WinAPI回調的優雅方式。假設我正在製作一個處理異步I/O的類。所有的Windows回調應該是stdcall函數,而不是類方法(例如,我需要將它們的地址傳遞給ReadFileEx WinAPI函數)。所以,我不能將方法地址作爲回調函數傳遞給WinAPI函數。在類中封裝WinAPI回調的最優雅的方式

什麼是最優雅的方式來封裝類中的這種類型的功能,以便該類有事件OnReadCompleted和OnWriteCompleted(我使用Delphi作爲主要語言,但我想情況必須在C++相同,因爲類方法不同於簡單的方法,事實上,它們的第一個隱藏參數是這個鏈接。當然這個類不是單例,並且可以有很多同時由應用程序創建的類。

你認爲這是實施這個的好方法嗎?

回答

4

我懷疑這是以任何方式優雅,但IMO,ea siest是將類的方法地址轉換爲過程地址並將其傳遞給winapi。當然,這是一個黑客攻擊,但是VCL與classes.MakeObjectInstance完全相同,只是針對特定的構造。請參閱this question,以獲取source這種實現方式以及其他一些OO方法來處理這種情況。

+0

我不知道這種方法是否能在未來的(遠?)64位delphi版本中使用(Proc調用在64中有很大不同)。我真的懷疑它。但現在沒有辦法說。 – ChristianWimmer 2010-06-06 11:21:05

2

您可以使用靜態關鍵字。但它只適用於新的Delphi版本。

像這樣:

type 
    TMyThread = class 
    private 
    // ... 

    class function ThreadProc(Param: Pointer): DWord; stdcall; static; // <- WinAPI call back 

    function Execute: DWord; // <- actual callback 
    public 
    constructor Create; 
    // ... 
    end; 

{ TMyThread } 

constructor TMyThread.Create; 
begin 
    // ... 
    FHandle := CreateThread(nil, 0, @ThreadProc, Self, 0, FID); 
end; 

class function TMyThread.ThreadProc(Param: Pointer): DWord; 
begin 
    Result := TMyThread(Param).Execute; 
end; 

function TMyThread.Execute: DWord; 
begin 
    MessageBox(0, 'Hello from thread', 'Information', MB_OK or MB_ICONINFORMATION); 
    Result := 0; 
end; 

這裏:ThreadProc的是WinAPI的回調例程。它需要有某種形式的自定義論證,你可以通過自我。它不能訪問實例成員。這就是爲什麼它只是真正的回調(Execute)的包裝,它是類的一部分,可以訪問它的字段和方法。

+0

如果確保回調(Execute)具有與WinAPI回調相同的二進制簽名,則也可以去掉包裝(ThreadProc)。在上面的例子中,你可以添加「stdcall」來完全執行和刪除ThreadProc,將@Execute傳遞給CreateThread。但這是一條危險的道路。 – Alex 2010-06-01 22:32:29

+0

謝謝,但我提到過,我的班級不是單身人士,應用程序中可能有很多這類班級的實例。所以,靜態方法解決方案不太好。除非可能我在某處存儲一個方法指針列表需要根據傳遞給回調的東西來調用。 – 2010-06-02 07:13:41

+0

@FractalizeR嗯......你爲什麼認爲只能創建一個實例?您可以使用任意數量的實例。請仔細研究我的例子。確切的實例被保存。 – Alex 2010-06-02 09:44:34

相關問題