digitalmars.D.learn - Use nested functions as callbacks with Windows API functions?
- spikespaz (37/37) Oct 01 2018 I have the following code, this works.
- Boris-Barboris (6/11) Oct 01 2018 You can make it a non-delegate by passing a pointer to hWndList
- spikespaz (18/30) Oct 01 2018 I don't know how to do this. I'm not the best with pointers, I'm
- spikespaz (24/36) Oct 01 2018 The problem with the code you have is that the callback needs to
- Boris-Barboris (4/7) Oct 01 2018 Neither do I actually. Apparently it is impossible.
- John Chapman (23/26) Oct 02 2018 I think the best you can do is something like this:
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.
Oct 01 2018
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
Oct 01 2018
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 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?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
Oct 01 2018
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: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) nothrowI 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
Oct 01 2018
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
Oct 01 2018
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); } ---
Oct 02 2018