Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
October 01, 2018 Use nested functions as callbacks with Windows API functions? | ||||
---|---|---|---|---|
| ||||
I have the following code, this works. ================================================================ 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); } ================================================================ I was hoping I could use something more akin to JavaScript's syntax: (void* hWnd, long) => {}. I tried this but I'm getting errors with the signature, it says the function is a delegate and apparently Windows API can't accept a delegate. ================================================================ 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); } ================================================================ I'm not going to even paste the compiler error because I am very clearly going about this the wrong way. Of course there is nothing wrong with defining each callback as a separate function, but then comes the issue of naming them. I also don't like the way it makes my code look. Thanks. |
October 01, 2018 Re: Use nested functions as callbacks with Windows API functions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to spikespaz | On Monday, 1 October 2018 at 20:27:43 UTC, spikespaz wrote: > I was hoping I could use something more akin to JavaScript's syntax: (void* hWnd, long) => {}. > > I tried this but I'm getting errors with the signature, it says the function is a delegate and apparently Windows API can't accept a delegate. You can make it a non-delegate by passing a pointer to hWndList in lParams as it was supposed to by WinApi devs, instead of zero, and not implicitly capturing stack pointer by referencing hWndList directly from the body. https://run.dlang.io/is/t4k4Nc |
October 01, 2018 Re: Use nested functions as callbacks with Windows API functions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Boris-Barboris | On Monday, 1 October 2018 at 21:03:24 UTC, Boris-Barboris wrote: > On Monday, 1 October 2018 at 20:27:43 UTC, spikespaz wrote: >> I was hoping I could use something more akin to JavaScript's syntax: (void* hWnd, long) => {}. >> >> I tried this but I'm getting errors with the signature, it says the function is a delegate and apparently Windows API can't accept a delegate. > > You can make it a non-delegate by passing a pointer to hWndList in lParams as it was supposed to by WinApi devs, instead of zero, and not implicitly capturing stack pointer by referencing hWndList directly from the body. > > https://run.dlang.io/is/t4k4Nc I don't know how to do this. I'm not the best with pointers, I'm still learning D and I'm unfamiliar with functional programming. ============================================== import core.sys.windows.windows: EnumWindows; import std.stdio: writeln; extern (Windows) int callback(void* hWnd, long hWndList) nothrow { hWndList ~= hWnd; return true; } void main() { void*[] hWndList; EnumWindows(&callback, &hWndList); writeln(hWndList); } ============================================== Clearly I can't use &hWndList to pass the reference, how would I access the variable by the memory address inside the callback? |
October 01, 2018 Re: Use nested functions as callbacks with Windows API functions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Boris-Barboris | On Monday, 1 October 2018 at 21:03:24 UTC, Boris-Barboris wrote: > On Monday, 1 October 2018 at 20:27:43 UTC, spikespaz wrote: >> I was hoping I could use something more akin to JavaScript's syntax: (void* hWnd, long) => {}. >> >> I tried this but I'm getting errors with the signature, it says the function is a delegate and apparently Windows API can't accept a delegate. > > You can make it a non-delegate by passing a pointer to hWndList in lParams as it was supposed to by WinApi devs, instead of zero, and not implicitly capturing stack pointer by referencing hWndList directly from the body. > > https://run.dlang.io/is/t4k4Nc The problem with the code you have is that the callback needs to be extern (Windows). I don't know how to do that with a "lambda". =========================================== import core.sys.windows.windows: EnumWindows; import std.stdio: writeln; void main() { void*[] hWndList; EnumWindows((void* hWnd, void* lParam) nothrow { *(cast(void*[] *) lParam) ~= hWnd; return true; }, &hWndList); writeln(hWndList); } =========================================== source\cb.d(7): Error: function core.sys.windows.winuser.EnumWindows(extern (Windows) int function(void*, long) nothrow, long) is not callable using argument types (bool function(void* hWnd, void* lParam) pure nothrow @system, void*[]*) source\cb.d(7): cannot pass argument __lambda1 of type bool function(void* hWnd, void* lParam) pure nothrow @system to parameter extern (Windows) int function(void*, long) nothrow |
October 02, 2018 Re: Use nested functions as callbacks with Windows API functions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to spikespaz | On Monday, 1 October 2018 at 23:07:29 UTC, spikespaz wrote: > The problem with the code you have is that the callback needs to be extern (Windows). I don't know how to do that with a "lambda". Neither do I actually. Apparently it is impossible. Best I could squeeze out was this: https://run.dlang.io/is/CpyfW3 |
October 02, 2018 Re: Use nested functions as callbacks with Windows API functions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to spikespaz | On Monday, 1 October 2018 at 20:27:43 UTC, spikespaz wrote:
> Of course there is nothing wrong with defining each callback as a separate function, but then comes the issue of naming them. I also don't like the way it makes my code look.
I think the best you can do is something like this:
---
auto callback(T, string file = __FILE__, size_t line = __LINE__)(T handler) {
import std.traits;
__gshared T handler_;
handler_ = handler;
extern(Windows)
ReturnType!T fn(Parameters!T args) {
synchronized return handler_(args);
}
return &fn;
}
void main() {
HWND[] list;
EnumWindows((HWND hwnd, LPARAM lparam) {
list ~= hwnd;
return TRUE;
}.callback(), 0);
writeln(list);
}
---
|
Copyright © 1999-2021 by the D Language Foundation