Calling C functions

Jacob Carlborg doob at me.com
Fri Jun 26 08:15:27 UTC 2020


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)?
>   cfunc(&dcallback);
>
> 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()
{
     printf("asd\n".ptr);
}

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

--
/Jacob Carlborg


More information about the Digitalmars-d-learn mailing list