使用嵌套函数作为 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
我有以下代码,这个有效。
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