2010-06-01 20 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

相关问题