www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - extern(C) delegate

reply "Mariusz `shd` =?UTF-8?B?R2xpd2nFhHNraSI=?= <alienballance gmail.com> writes:
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?
Dec 04 2013
parent =?UTF-8?B?UsOpbXkgTW91w6t6YQ==?= <remy.moueza gmail.com> writes:
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 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?
Dec 04 2013