Using delegates for C callbacks.
Kirk McDonald
kirklin.mcdonald at gmail.com
Fri Feb 1 14:23:40 PST 2008
Leandro Lucarella wrote:
> Hi! I'm doing some code to interface with C and I need to use D delegates
> as C callbacks.
>
> I've tested a lot of posibilities to do this, asking on IRC channels, but
> nothing seems to work entirely.
[snip]
>
> The thunk for the plain function adaptation works fine, but not the
> delegate. If I uncomment the code at line 33 I get:
>
> thunk.d:10: Error: need 'this' to access member dcb
>
> I have a void* pointer to use, I can "inject" the this pointer, but I
> don't know how. Doing something like:
>
> 8 extern (C) static void thunk(alias Fn)(void* arg)
> 9 {
> 10 Fn.ptr = arg;
> 11 Fn();
> 12 }
>
> Doesn't work, it says:
> thunk.d:10: Error: no property 'ptr' for type 'void'
> thunk.d:10: Error: constant dcb().ptr is not an lvalue
> thunk.d:10: Error: cannot implicitly convert expression (arg) of type void* to int
>
> Which I don't understand (specially the part of "no property 'ptr' for
> type 'void'", why dcb is void? I don't think I understand very well the
> semantics of an alias template parameter =S
>
>
> Is there any recomended solution for this? I think it (or should be) a
> fairly common problem (at least when making D bindings for C libraries).
>
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);
}
--
Kirk McDonald
http://kirkmcdonald.blogspot.com
Pyd: Connecting D and Python
http://pyd.dsource.org
More information about the Digitalmars-d-learn
mailing list