extern(C) delegate

Rémy Mouëza remy.moueza at gmail.com
Wed Dec 4 12:20:41 PST 2013


I had played with that idea and searched the forums once.
I came up with the following proof-of-concept code.

in C  (c_dg.c) {
     #include <stdio.h>

     /// This is how a delegate is implemented (currently).
     typedef struct Dg {
         /// The context (class instance or frame or null).
         void * ctx;
         /// The function pointer that takes a first extra parameter
         /// for the context.
         const char * (*fn) (void * ctx, int i, int j);
     } Dg;

     void callDg (Dg dg) {
         if (dg.fn == NULL) {
             printf ("it's null.\n");
         } else {
             // This calls the D delegate from C.
             // One has to pass dg.ctx as first argument.
             printf ("result: %s\n", dg.fn (dg.ctx, 42, 7));
         }
     }
}

in D (ddg.d) {
     import std.stdio;
     import std.string;
     import std.conv;

     extern (C) void callDg (immutable(char)* delegate (int, int));

     class X {

         extern (C)
         immutable(char)* callMe (int i, int j) {
             return "%d, %d".format (i, j).toStringz;
         }
     }

     void main () {
         auto x = new X;
         callDg (&x.callMe); // Call with a non null delegate.
         callDg (null);  // Case with null.
     }
}

I compile and run with: `gcc -c c_dg.c && dmd ddg.d c_dg.o && ./ddg`

The program outputs:
result: 42, 7
it's null.

You should also be aware that the current implementation of delegates 
are not officially documented and may change in a future version of D. 
However, from what I understand, it's been implemented like this for 
quite a while and is unlikely to change any soon.
Use at your own risk and have fun!

On 12/04/2013 08:27 PM, "Mariusz `shd` Gliwiński" 
<alienballance at gmail.com>" wrote:
> I'd like to expose my D API to C code.
> For that, i'm going to write templates generate extern(C) definition
> alongside of D-one.
> One thing i could do, is to generate D struct that mimics delegate with
> appropriate arguments. However, i'm curious of another possibility:
>
> How do i call
> extern(C) void test(int delegate(int) dlg = null)
> from non-extern D code?



More information about the Digitalmars-d-learn mailing list