Function Pointer Not Working

Vladimir Panteleev thecybershadow.lists at gmail.com
Thu Nov 19 05:29:53 UTC 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


More information about the Digitalmars-d-learn mailing list