代码之家  ›  专栏  ›  技术社区  ›  Vladislav Rastrusny

在类中封装winapi回调的最优雅的方法[重复]

  •  3
  • Vladislav Rastrusny  · 技术社区  · 15 年前

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

    在类中封装这种类型的功能是最优雅的方式,以便类具有读写完成和写写的事件(我使用Delphi作为主语言),但我认为C++中的情况必须相同,因为类方法不同于简单方法,事实上,第一个隐藏参数是它们是 链接。当然,这个类不是一个单独的类,应用程序可以同时创建许多类。

    你认为什么是实现这一目标的好方法?

    2 回复  |  直到 15 年前
        1
  •  4
  •   Community CDub    8 年前

    我怀疑这是否优雅,但是,在我看来,最简单的方法是将类的方法地址转换为过程地址并将其传递给winapi。当然,这是一个黑客,但录像机对 classes.MakeObjectInstance ,如果仅针对特定构造..见 this question 对于一个 source 对于这种实现和其他一些更面向对象的方法来处理这种情况。

        2
  •  2
  •   Alex    15 年前

    你可以使用 静止的 关键字。但它只能在新的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)的包装器,它是类的一部分,可以访问它的字段和方法。