www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Function Pointer Not Working

reply Marcone <marcone email.com> writes:
// 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
next sibling parent reply Vladimir Panteleev <thecybershadow.lists gmail.com> writes:
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
parent Marcone <marcone email.com> writes:
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
prev sibling parent reply Kagamin <spam here.lot> writes:
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
parent reply Marcone <marcone email.com> writes:
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
parent Marcone <marcone email.com> writes:
I will wait with this code.
WaitForSingleObject(threading, INFINITE);
Nov 19 2020