我正在考虑在类中封装WinAPI回调的优雅方法。假设我正在创建一个处理异步I / O的类。所有Windows回调都应该是stdcall函数,而不是类方法(我需要将它们的地址传递给ReadFileEx WinAPI函数)。所以,我不能只将方法地址作为回调例程传递给WinAPI函数。
在类中封装此类功能的最优雅方法是什么,以便类具有事件OnReadCompleted和OnWriteCompleted(我使用Delphi作为主要语言,但我想C ++中的情况必须相同,因为类方法与简单方法的不同之处在于,它们的第一个隐藏参数是 this 链接。当然这个类不是单例,并且可以有很多app同时由app创建
您认为实施此方法的好方法是什么?
答案 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)的包装器,它是类的一部分,可以访问它的字段和方法。