在类中封装WinAPI回调的最优雅方法

时间:2010-06-01 20:26:46

标签: delphi winapi callback

我正在考虑在类中封装WinAPI回调的优雅方法。假设我正在创建一个处理异步I / O的类。所有Windows回调都应该是stdcall函数,而不是类方法(我需要将它们的地址传递给ReadFileEx WinAPI函数)。所以,我不能只将方法地址作为回调例程传递给WinAPI函数。

在类中封装此类功能的最优雅方法是什么,以便类具有事件OnReadCompleted和OnWriteCompleted(我使用Delphi作为主要语言,但我想C ++中的情况必须相同,因为类方法与简单方法的不同之处在于,它们的第一个隐藏参数是 this 链接。当然这个类不是单例,并且可以有很多app同时由app创建

您认为实施此方法的好方法是什么?

2 个答案:

答案 0 :(得分:4)

我怀疑这在任何方面都很优雅,但是,IMO,最简单的方法是将类方法的地址转换为过程地址并将其传递给winapi。当然,这是一个黑客攻击,但是VCL对classes.MakeObjectInstance执行的操作与{{1}}完全相同,如果仅适用于特定的构造。请参阅this question了解source这种实现以及其他一些实现方法,更多OO方式来处理这种情况。

答案 1 :(得分:2)

您可以使用 static 关键字。但它仅在新的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回调例程。它需要具有某种形式的自定义参数,您可以在其中传递Self。它无法访问实例成员。这就是为什么它只是真正的回调(Execute)的包装器,它是类的一部分,可以访问它的字段和方法。