Using delegates for C callbacks.

Leandro Lucarella llucax at gmail.com
Fri Feb 1 21:11:31 PST 2008


Leandro Lucarella, el  2 de febrero a las 02:17 me escribiste:
> Is this too wrong? I guess the casting from dg.funcptr to an extern (C)
> function is not (I don't know if D calling convention is warrantied to be
> the same as C, and I don't know if is warrantied that the first argument
> to a delegate is the context pointer), but I really want the generality
> and simplicity of this code, it makes no sense to need code more complex
> than that to do what I want to do.

Well, it was that wrong, it only worked with delegates without arguments.
I saw that the D calling conventions are defined in the D ABI
specification so they aren't always the same as the C calling conventions,
I guess.

I finally decided to go with this:


import std.stdio;

extern(C) void c_f(void function(int, void*) fn, int data, void* closure) {
        fn(data, closure);
}

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

struct Delegate
{
        void delegate(int) dg;
}

extern (C) void thunk(int revents, void* data)
{
        auto d = cast (Delegate*) data;
        d.dg(revents);
}

void d_f(void delegate(int) dg, int data)
{
        auto d = new Delegate;
        d.dg = dg;
        c_f(&thunk, data, d);
}

void main() {
        void foo(int data) {
                writefln("foo: data=", data);
        }
        C c = new C;
        c.x = 1;
        d_f(&foo, 10);
        d_f(&c.foo, 5);
}


I'm not crazy about the heap allocation, but at least is simple, safe and
general. And the templated thunk version wont work either if I want the
API usage to be simple (with templates, users will be forced to pass the
function pointer, which can be calculated at compile-time, separated from
the context pointer, which is always a runtime value).

-- 
Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/
----------------------------------------------------------------------------
GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)
----------------------------------------------------------------------------
JUGAR COMPULSIVAMENTE ES PERJUDICIAL PARA LA SALUD.
	-- Casino de Mar del Plata


More information about the Digitalmars-d-learn mailing list