Create a delegate function

Adam D. Ruppe via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat Sep 5 12:14:39 PDT 2015


On Saturday, 5 September 2015 at 18:00:53 UTC, Prudence wrote:
> I have code setup in such a way that I call a user defined 
> function, e.g.,
>
> void myFunc(Data d)
> {
> ....
> }
>
> myFunc has to be passed to the main code using something like


You can do that if and only if the this is the last argument to 
the function and is a pointer.

Even then, you're kinda hacking it, but with casts you can make 
it work:

struct Test {
         int a;
}
void foo(Test* _this) {
         _this.a = 10;
}
void main() {
         auto _this = new Test();
         void delegate() dg;
         dg.funcptr = cast(typeof(dg.funcptr)) &foo;
         dg.ptr = _this;
         dg();
         import std.stdio;
         writeln(_this.a);
}



You could probably put that in a template that does better type 
checking.


But the idea is that a delegate is simply a pair of function 
pointer and context pointer. When you call it, it automatically 
adds the context pointer as the last hidden argument to the 
function.

Knowing how it works at the low level, we can use some casts to 
get the compiler to trust us and make it work.


Similarly with arguments:


struct Test {
         int a;
}
void foo(int a, Test* _this) {
         _this.a = 10 + a;
}
void main() {
         auto _this = new Test();
         void delegate(int) dg;
         dg.funcptr = cast(typeof(dg.funcptr)) &foo;
         dg.ptr = _this;
         dg(10);
         import std.stdio;
         writeln(_this.a);
}



To type check this, you could probably use 
ParameterTypeTuple!foo[0 .. $-1] and check for match there on the 
typeof(dg.funcptr). And check return value and that the last 
argument is indeed a pointer of the type you are giving.



More information about the Digitalmars-d-learn mailing list