digitalmars.D.learn - Function Pointer Not Working
- Marcone (16/16) Nov 18 2020 // Function threadingw()
- Vladimir Panteleev (74/90) Nov 18 2020 A delegate is a "fat" pointer (function pointer + context), so it
- Marcone (5/5) Nov 19 2020 Solved replacing this line:
- Kagamin (4/4) Nov 19 2020 The delegate is stored on the stack of the calling thread, the
// Function threadingw() void threadingw(HWND hwn, void delegate() fun) nothrow { try { // Function _fun() extern(Windows) uint _fun(void * arg){ (*(cast(void delegate()*) arg))(); // Do not show "Hello World!" :( return 0; } CreateThread(null, 0, &_fun, &fun, 0, null); } catch(Throwable){} } void main(){ null.threadingw({writeln("Hello World!");}); }
Nov 18 2020
On Thursday, 19 November 2020 at 04:23:13 UTC, Marcone wrote:// Function threadingw() void threadingw(HWND hwn, void delegate() fun) nothrow { try { // Function _fun() extern(Windows) uint _fun(void * arg){ (*(cast(void delegate()*) arg))(); // Do not show "Hello World!" :( return 0; } CreateThread(null, 0, &_fun, &fun, 0, null); } catch(Throwable){} } void main(){ null.threadingw({writeln("Hello World!");}); }A delegate is a "fat" pointer (function pointer + context), so it can't fit in a void*. You could do something like the following to "uncurry" the delegate and extract its context to a void* and a regular function, which can then combine the void* given to it later to call the original delegate: import std.traits; auto uncurryDelegate(alias anchor, alias target)() { alias Args = Parameters!target; alias R = ReturnType!target; alias ContextPtr = void*; alias Dg = typeof(&target); union Delegate { Dg dg; struct { void* ptr; void* funcptr; } } auto dg = Delegate(&target); __gshared void* funcptr; // Will always be the same for this instantiation funcptr = (&target).funcptr; static struct Result { R function(ContextPtr ptr, Args args) fun; ContextPtr context; } static R fun(ContextPtr ptr, Args args) { Delegate dg; dg.funcptr = funcptr; dg.ptr = ptr; return dg.dg(args); } return Result(&fun, dg.ptr); } auto uncurryDelegate(alias target)() { return uncurryDelegate!(target, target); } unittest { int fun(int i) { return i + 1; } auto r = uncurryDelegate!fun; assert(r.fun(r.context, 2) == 3); } unittest { struct S { int i; int fun(int j) { return i + j; } auto funUncurried() { return uncurryDelegate!(i, fun); } } auto s = S(2); auto r = s.funUncurried(); assert(r.fun(r.context, 3) == 5); } Sadly you can't write `static immutable void* funcptr = (&target).funcptr;`, because the compiler tries to evaluate &target first. Alternatively you could do this (not recommended): https://stackoverflow.com/a/8656294/21501
Nov 18 2020
Solved replacing this line: CreateThread(null, 0, &_fun, &fun, 0, null); to this code: task!({CreateThread(null, 0, &_fun, &fun, 0, null);}).executeInNewThread();
Nov 19 2020
The delegate is stored on the stack of the calling thread, the created thread loads it from there, but the calling thread doesn't wait for that and clobbers the stack right away. If you were lucky your code would crash.
Nov 19 2020
On Thursday, 19 November 2020 at 15:51:09 UTC, Kagamin wrote:The delegate is stored on the stack of the calling thread, the created thread loads it from there, but the calling thread doesn't wait for that and clobbers the stack right away. If you were lucky your code would crash.The thread that I do wait ultil function is finished. Using a while with 3 seconds to verify if thread id is in running list, and break if not finishing owner thread.
Nov 19 2020
I will wait with this code. WaitForSingleObject(threading, INFINITE);
Nov 19 2020