【问题标题】:How to pass the address of a thread function as a callback to winapi?如何将线程函数的地址作为回调传递给winapi?
【发布时间】:2011-10-09 21:23:52
【问题描述】:

我有一个简单的线程,在执行过程中,我尝试使用线程中定义的函数之一的地址调用 EnumWindows()。 所以我正在尝试这样做: EnumWindows(@cbEnumWindowsClickOK, 0);其中 cbEnumWindowsClickOK 是在线程类中定义的 EnumWindowProc,如下所示:

TAutoClickOKThread = class(TThread)
private
     fExitEvent : THandle;
     function cbEnumWindowsClickOK(Wnd: HWND; Info: Pointer): BOOL;
public
   constructor Create(ExitEvent : Thandle);
   procedure Execute(); override;
end;

当我尝试这个时,我不断收到“错误:需要变量”,暗示它不会将 @cbEnumWindowsClickOK 解释为地址。如果我将函数移动到全局范围(从线程中删除它),它确实可以工作。

有什么想法可以解决这个问题吗?

【问题讨论】:

  • +1:请考虑post。谢谢。

标签: multithreading delphi winapi pointers


【解决方案1】:

您必须传递 EnumWindows 一个普通的旧函数,即未绑定到实例的函数。您必须单独传递实例。像这样:

function EnumFunc(hwnd: HWND; lParam: LPARAM): BOOL; stdcall;
begin
  Result := TAutoClickOKThread(lParam).cbEnumWindowsClickOK(hwnd);
  //note that there is now no need for the Info parameter
end;
...
procedure TAutoClickOKThread.Execute;
begin
  ...
  EnumWindows(EnumFunc, LPARAM(Self));
  ...
end;

必须这样做的原因是实例方法与EnumWindows 所需的签名不匹配。实例方法有一个包含实例引用的额外隐式参数,即Self。这就是您能够引用实例成员的方式。但是EnumFunc 的签名不适合这个。

【讨论】:

  • 如果声明为static', but you still need to use the callback's lParam`参数,您可以使用类方法来传递Self指针。
  • @Remy 虽然这也有效,但我不确定它是否更好。特别是如果在接口部分声明了类,那么在我看来,这种方法会导致额外的混乱。
  • @David 我觉得你不能从类中传递方法的地址有点奇怪。据我所知,每个类只有一个函数实例,并且所有类实例都使用同一个实例,因此似乎很合乎逻辑,可以获得该函数地址...
  • @Ran 实例函数的签名错误。那就是问题所在。实例函数有一个额外的隐式参数,即实例。
  • @David:在 Delphi 中,使用静态类方法除了用于代码组织之外没有其他用处,因为单元中的所有内容彼此之间都有隐含的友谊。在不存在隐式友谊的 C/C++ 中,使用静态类方法作为回调更有用。
猜你喜欢
  • 1970-01-01
  • 2022-11-25
  • 2018-08-09
  • 2020-08-16
  • 2021-02-23
  • 2020-11-14
  • 1970-01-01
  • 1970-01-01
  • 2013-04-12
相关资源
最近更新 更多