Thread overview
Function Pointer Not Working
Nov 19, 2020
Marcone
Nov 19, 2020
Vladimir Panteleev
Nov 19, 2020
Marcone
Nov 19, 2020
Kagamin
Nov 19, 2020
Marcone
Nov 19, 2020
Marcone
November 19, 2020
// 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!");});

}
November 19, 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
November 19, 2020
Solved replacing this line:

CreateThread(null, 0, &_fun, &fun, 0, null);

to this code:
task!({CreateThread(null, 0, &_fun, &fun, 0, null);}).executeInNewThread();
November 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.
November 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.
November 19, 2020
I will wait with this code.
WaitForSingleObject(threading, INFINITE);