Function 是否将嵌套函数用作Windows API函数的回调?

Function 是否将嵌套函数用作Windows API函数的回调?,function,winapi,callback,window,d,Function,Winapi,Callback,Window,D,我有以下代码,这是可行的 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() { EnumWindow

我有以下代码,这是可行的

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文档为指定的正确签名

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

这就是我用来创建正确签名的方法

alias EnumWindowsProc = extern (Windows) int function(HWND, LPARAM) nothrow;
然后,我发现别名已经作为
ENUMWINDOWSPROC
存在于
core.sys.windows.windows
第2483行的MinGW标题中(在撰写本文时)

为了解决隐式传递D帧的问题,我使用了
cast(LPARAM)&hwnlist
作为中的
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);
}
我希望这能帮助一些人,因为这让我非常困惑(仍然不确定我是否理解指针逻辑)

感谢Boris Barboris在D论坛上给了我一些工作的素材


我建议您尝试嵌套的静态函数。我可以稍后再写,不确定它是否允许extern(Windows)作为嵌套函数,但它可能会,然后您可以在调用之前的行上定义并在此处使用它。回调必须严格遵守预期的签名。嵌套(如C++ LAMDA)函数与此签名不匹配。因为嵌套函数实际上是某个未命名对象上的成员函数,并且它有额外的隐藏参数(如下图所示),所以在回调中如何访问
hwnlist
?因为指向此局部变量的指针保存在本地回调所在的隐藏局部对象中。无论如何,您需要静态函数作为回调函数。在本地对象上是可能的,但您是否为64位编译?您的代码我很确定它在32位上是错误的-C长和D长实际上通常不兼容(LPRAM实际上更像是
void*
而不是long本身)@AdamD.Ruppe Nope,这是32位的。是的,那么它肯定是错误的,它现在正好可以工作,因为32位指针将适合长字符串的前几个字节,但这可能会导致堆栈损坏,因为函数试图清理8个字节,但没有意识到实际上有12个字节。您需要将该长度更改为
c_long
,位于
import core.stdc.config,或到
无效*
@AdamD.Ruppe工作正常,无参数,
-m32
-m64
。这是一个Windows函数,因此我无法更改为
void
指针。无论如何,我尝试过。我刚刚尝试过,但您的代码甚至无法在32位上编译。(这比堆栈损坏更好!)。你的设置一定有点奇怪,也许m32被某个全局配置覆盖了<代码>无法将long类型的参数强制转换(long)和hwnlist传递给参数int
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);
}