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"
<alienballa...@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?