On Friday, 26 June 2020 at 00:30:22 UTC, Denis wrote:
I have a two questions about calling C functions from D.

(1) When passing a D callback to a C function, is there a way to write the code without having to prefix the callback declaration with "extern(C)"?

It's not a big deal adding the prefix to the D function declaration. It just seems odd to me to prefix D code with "extern(C)". For example, the following code works:

  extern(C) void cfunc(void function(int));
  extern(C) void dcallback(int x) {...}         <-- Why extern(C)?

Can this be rewritten, dropping the prefix from the second line? If not, it would be helpful to know why "extern(C)" is needed here too.

No, it cannot be dropped. `extern(C)` is required because C and D are using different calling conventions (D functions are also mangled). For example, D (at least DMD and LDC) are passing the arguments to the function in reverse.

(2) Is there a way to restrict the invocation of a linked C function to one specific D function?

If the C header is defined in one of the core.stdc libraries, the import statement can either be global or inside a specific D function -- both work. In contrast, when the C function prototype is written directly into the D program (as above), the linker complains unless this declaration is made global. If it's possible to restrict the scope of the C function to just one D function, I'll take advantage.

For functions nested in a D language construct (class, struct, function) the compiler will always use the D mangling, instead of the C mangling. In theory it would be possible to workaround that by forcing the mangled name using `pragma(mangle)`, but for some reason the compiler doesn't allow `pragma(mangle)` inside a function body, on a nested function declaration.

You can wrap up everything in a struct, as follows:

struct printf
pragma(mangle, "printf") extern (C) private static int printf(in char*, ...);

    static int opCall(Args...)(Args args)
        return printf(args);

void main()

The `printf` function can be called from anywhere within the module, but not outside the module.

/Jacob Carlborg

Reply via email to