Using delegates for C callbacks.

Leandro Lucarella llucax at gmail.com
Fri Feb 1 16:09:34 PST 2008


Kirk McDonald, el  1 de febrero a las 14:23 me escribiste:
[snip]
> Try something like this:
> 
> extern(C) void f(void function(void*) fn, void* closure) {
>     fn(closure);
> }
> 
> class C {
>     void foo(int i) {}
> }
> 
> struct Closure {
>     C self;
>     int arg;
> }
> 
> // It is possible to do some template trickery in order to
> // generalize this thunk for any function signature and any
> // class, but it is simpler to get the point across with a
> // concrete example.
> extern(C) void thunk(alias Fn)(void* _closure) {
>     void delegate(int) dg;
>     Closure* closure = cast(Closure*)_closure;
>     dg.funcptr = &Fn;
>     dg.ptr = cast(void*)(closure.self);
>     dg(closure.arg);
> }
> 
> void main() {
>     C c = new C;
>     auto closure = new Closure;
>     closure.self = c;
>     closure.arg = 20;
>     // Note that we're passing the function C.foo and not
>     // the method c.foo.
>     thunk!(C.foo)(closure);
>     f(&thunk!(C.foo), closure);
> }

Thanks, Kirk! The trick about passing the C.foo function instead of the
c.foo method was defenely the trick. I adapted your example to what I
needed, which is simpler because I don't need the Closure wrapper, so the
code is more general without extra complexity:

import std.stdio;

extern(C) void f(void function(void*) fn, void* closure) {
        fn(closure);
}

class C {
        int x;
        void foo() {
                writefln("foo: ", x);
        }
}

// It is possible to do some template trickery in order to
// generalize this thunk for any function signature and any
// class, but it is simpler to get the point across with a
// concrete example.
extern(C) void thunk(alias Fn)(void* closure) {
        void delegate() dg;
        dg.funcptr = &Fn;
        dg.ptr = closure;
        dg();
}

void main() {
        C c = new C;
        // Note that we're passing the function C.foo and
        // not the method c.foo.
        c.x = 1;
        thunk!(C.foo)(cast (void*) c);
        c.x = 2;
        f(&thunk!(C.foo), cast (void*) c);
}

PS: Thanks BCS for the answer. I didn't try it either because I didn't
understand it and found it too twisted, I was looking for something
simpler :)

-- 
Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/
----------------------------------------------------------------------------
GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)
----------------------------------------------------------------------------
Dentro de 30 aņos Argentina va a ser un gran supermercado con 15
changuitos, porque esa va a ser la cantidad de gente que va a poder
comprar algo.
	-- Sidharta Wiki


More information about the Digitalmars-d-learn mailing list