www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Linkage question

reply frame <frame86 live.com> writes:
If I declare a function as extern(C) inside a DLL, I have also to 
cast the function pointer as extern(C) or it fails calling, eg.

```d
// --- my.dll
export extern (C) void log(int mode, string a, string b, string 
c) {
   /* stuff */
}

// --- main.d
alias T = extern (C) void function(int, string, string, string);
auto fnPtr = cast(T)GetProcAddress(/* stuff */);
```

I understand that the linkage must match but besides the name 
mangling, what's happen here? What is the difference if I remove 
the `extern (C)` part from the T alias?

Doing that supplies 2nd and 3rd paramter as fine pointers but the 
1st argument comes wrong (eg. 10 becomes -218697648) and the last 
argument is garbage too, so the D-linkage format is something 
different.

Would like to know where the linkage format is defined, thx.
Jan 24 2022
parent reply Stanislav Blinov <stanislav.blinov gmail.com> writes:
On Monday, 24 January 2022 at 17:23:01 UTC, frame wrote:

 I understand that the linkage must match but besides the name 
 mangling, what's happen here? What is the difference if I 
 remove the `extern (C)` part from the T alias?
The difference is in how arguments are being passed, which you seem to have discovered already :)
 Would like to know where the linkage format is defined, thx.
It should be here: https://dlang.org/spec/abi.html although IIRC it might not be 100% up to date.
Jan 24 2022
parent reply frame <frame86 live.com> writes:
On Monday, 24 January 2022 at 18:30:02 UTC, Stanislav Blinov 
wrote:

 The difference is in how arguments are being passed, which you 
 seem to have discovered already :)

 Would like to know where the linkage format is defined, thx.
It should be here: https://dlang.org/spec/abi.html although IIRC it might not be 100% up to date.
Ah, yes. Thanks. Maybe I should read it more carefully =) It claims that the D calling convention matches C. But it seems that the arguments are pushed in order whereas C does it in reverse order and the -218697648 value is indeed my 3rd string pointer.
Jan 24 2022
next sibling parent Paul Backus <snarwin gmail.com> writes:
On Monday, 24 January 2022 at 19:41:30 UTC, frame wrote:
 It claims that the D calling convention matches C. But it seems 
 that the arguments are pushed in order whereas C does it in 
 reverse order and the -218697648 value is indeed my 3rd string 
 pointer.
Windows has two calling conventions for C functions, `cdecl` and `stdcall`. In D, `cdecl` is called `extern (C)` and `stdcall` is called `extern (Windows)`. Windows API functions use the `stdcall` convention [1], so you need to use `extern (Windows)` when calling them from D. [1] https://docs.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-170
Jan 24 2022
prev sibling parent duser <duser neet.fi> writes:
On Monday, 24 January 2022 at 19:41:30 UTC, frame wrote:
 On Monday, 24 January 2022 at 18:30:02 UTC, Stanislav Blinov 
 wrote:

 The difference is in how arguments are being passed, which you 
 seem to have discovered already :)

 Would like to know where the linkage format is defined, thx.
It should be here: https://dlang.org/spec/abi.html although IIRC it might not be 100% up to date.
Ah, yes. Thanks. Maybe I should read it more carefully =) It claims that the D calling convention matches C. But it seems that the arguments are pushed in order whereas C does it in reverse order and the -218697648 value is indeed my 3rd string pointer.
that's a bug with dmd or the spec, arguments are currently passed in reverse order compared to C on 64-bit even though they should be the same see: https://issues.dlang.org/show_bug.cgi?id=20204 https://github.com/dlang/dmd/pull/13287 https://github.com/dlang/dlang.org/pull/3120
Jan 24 2022