wrapping a C style delegate
Nicholas Wilson via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Fri Aug 25 17:49:20 PDT 2017
On Saturday, 26 August 2017 at 00:27:47 UTC, Ali Çehreli wrote:
> I think you need a variation of intermediateCallback() below. I
> passed the address of the delegate as userData but you can
> construct any context that contains everything that you need
> (e.g. the address of ms).
>
> import std.stdio;
>
> // The C struct
> struct Struct {
> int i;
> }
>
> // Some C type
> enum ErrorEnum {
> zero
> }
>
> // Some C function taking a callback
> ErrorEnum SomeAPIaddCallback(Struct* s, void function(Struct*,
> ErrorEnum status, void *userData) callback, void *userData,
> uint flags) {
> writeln("SomeAPIaddCallback called for object ", s);
> writeln("Calling the callback...");
> callback(s, ErrorEnum.zero, userData);
> return ErrorEnum.zero;
> }
>
> // The callback to pass to the C function
> void intermediateCallback(Struct * s, ErrorEnum status, void
> *userData) {
> writeln("intermediateCallback called");
> auto cb = cast(void delegate(ErrorEnum)*)userData;
> (*cb)(status);
> }
>
> // The D wrapper always passes intermediateCallback to the C
> function
> struct MyStruct {
> Struct * s;
> void addCallback(void delegate(ErrorEnum ee) callback) {
> SomeAPIaddCallback(s, &intermediateCallback, &callback,
> 0);
> }
> }
>
> void main() {
> auto s = Struct(42);
> auto ms = MyStruct(&s);
> ms.addCallback((ErrorEnum ee) {
> writefln("The callback is called with %s for %s",
> ee, ms.s);
> });
> }
>
> Ali
I was thinking of something along those lines: but what about the
lifetime of the passed delegate (the address of a local
variable)? How can I ensure that it won't segfault when callback
goes out of scope?
I could new it with the GC but
a) I'd rather have the wrapper be @nogc and
b) i'd have to hold a reference to it or pin it because
SomeAPIaddCallback will be in a driver somewhere and wouldn't get
scanned by the GC.
More information about the Digitalmars-d-learn
mailing list