使用嵌套函数作为 Windows API 函数的回调?

Use nested functions as callbacks with Windows API functions?

我有以下代码,这个有效。

import core.sys.windows.windows: EnumWindows;
import std.stdio: writeln;

void*[] hWndList;

extern (Windows) int callback(void* hWnd, long /* lParams */ ) nothrow {
    hWndList ~= hWnd;

    return true;
}

void main() {
    EnumWindows(&callback, 0);

    writeln(hWndList);
}

我希望我可以使用更类似于 JavaScript 语法的东西:(void* hWnd, long) => {}.

我试过了,但签名出错,它说函数是委托,显然 Windows API 不能接受委托。

import core.sys.windows.windows: EnumWindows;
import std.stdio: writeln;

void main() {
    void*[] hWndList;

    EnumWindows((void* hWnd, long /* lParams */ ) nothrow {
        hWndList ~= hWnd; return true;
    }, 0);

    writeln(hWndList);
}

我什至不打算粘贴编译器错误,因为我非常清楚地以错误的方式解决这个问题。

当然,将每个回调定义为一个单独的函数并没有错,但是随之而来的是命名它们的问题。我也不喜欢它使我的代码看起来的方式。

谢谢。

我发现我可以将委托(或 lambda)转换为 MSDN 文档为 EnumWindowsProc 指定的正确签名。

我也没有意识到通过从全局范围隐式使用 hWndList 来访问 D 程序的框架是非常糟糕的做法。

这是我用来创建正确签名的。

alias EnumWindowsProc = extern (Windows) int function(HWND, LPARAM) nothrow;

然后我发现别名已经作为 ENUMWINDOWSPROC 存在于 MinGW headers 的 core.sys.windows.windows 的第 2483 行(在撰写本文时)。

extern (Windows) nothrow {
    ...
    alias BOOL function(HWND, LPARAM) ENUMWINDOWSPROC;
    ...
}

为了解决隐式传递 D 的框架的问题,我使用 cast(LPARAM) &hWndList 作为 EnumWindows 中的 lParam

这成为现在使用指针的问题。我知道这可能是拙劣的,欢迎任何建议,但我将其转换为指针。

*(cast(HWND[]*) lParam)

完整代码如下所示。显然,这只是开始时的一个最小示例,因此您可能希望将转换后的指针分配给某些东西,这样在使用来自 lParams.

的变量时就不会那么混乱了。
import core.sys.windows.windows: EnumWindows, ENUMWINDOWSPROC;
import std.stdio: writeln;

void main() {
    HWND[] hWndList;

    EnumWindows(cast(ENUMWINDOWSPROC) (HWND hWnd, LPARAM lParam) {
        *(cast(HWND[]*) lParam) ~= hWnd;
        return true;
    }, cast(LPARAM) &hWndList);

    writeln(hWndList);
}

我希望这对某些人有所帮助,因为这让我非常困惑(仍然不确定我是否理解指针逻辑)。

感谢 D 论坛上的 Boris-Barboris 给了我一些工作的机会。

https://forum.dlang.org/post/xxklxaajptppockvazeo@forum.dlang.org