digitalmars.D.learn - Linking external functions?
- DLearner (31/32) Apr 18 2023 Wanted to try out linking two source files independantly compiled.
Wanted to try out linking two source files independantly compiled.
ExtCallee.d source file:
```
extern(C) void ExtCallee() {
import std.stdio;
writeln("Entered: ", __FUNCTION__);
writeln("Exiting: ", __FUNCTION__);
}
```
ExtMain.d source file:
```
void main() {
import std.stdio;
extern(C) void ExtCallee();
writeln("Entered: ", __FUNCTION__);
ExtCallee();
writeln("Exiting: ", __FUNCTION__);
}
```
Then:
```
dmd ExtCallee -c
```
which worked, producing .obj file.
However:
```
dmd ExtCallee.obj -run ExtMain
lld-link: error: undefined symbol: __D7ExtMain4mainFZ9ExtCalleeUZv
referenced by ExtMain.obj:(__Dmain)
Error: linker exited with status 1
```
Ideas?
Apr 18 2023
On Tuesday, 18 April 2023 at 19:49:04 UTC, DLearner wrote:
```
void main() {
import std.stdio;
extern(C) void ExtCallee();
```
Move that declaration out of main.
Apr 18 2023
On Tuesday, 18 April 2023 at 20:00:18 UTC, ag0aep6g wrote:On Tuesday, 18 April 2023 at 19:49:04 UTC, DLearner wrote:Thanks - worked! Is the declaration inside main not visible to the linker?``` void main() { import std.stdio; extern(C) void ExtCallee(); ```Move that declaration out of main.
Apr 18 2023
On Tuesday, 18 April 2023 at 20:05:05 UTC, DLearner wrote:Is the declaration inside main not visible to the linker?It affects the (fully qualified and mangled) name of the function. Compare: ```d extern(C) void ExtCallee(); pragma(msg, ExtCallee.mangleof); /* ExtCallee (correct name) */ void main() { extern(C) void ExtCallee(); pragma(msg, ExtCallee.mangleof); /* _D7ExtMain4mainFZ9ExtCalleeUZv (incorrect) */ } ``` I don't know the rationale behind that behavior, if there is one. Generally, just put your `extern(C)` prototypes in module scope.
Apr 18 2023
DLearner via Digitalmars-d-learn wrote:
Wanted to try out linking two source files independantly compiled.
ExtCallee.d source file:
```
extern(C) void ExtCallee() {
import std.stdio;
writeln("Entered: ", __FUNCTION__);
writeln("Exiting: ", __FUNCTION__);
}
```
ExtMain.d source file:
```
void main() {
import std.stdio;
extern(C) void ExtCallee();
writeln("Entered: ", __FUNCTION__);
ExtCallee();
writeln("Exiting: ", __FUNCTION__);
}
What is the advantage of using extern(C)?
Since both are D source files, why wouldn't you do just this:
```d
// ExtCallee.d
void ExtCallee()
{
import std.stdio;
writeln("Entered: ", __FUNCTION__);
writeln("Exiting: ", __FUNCTION__);
}
```
```d
// ExtMain.d
void main()
{
import std.stdio;
import ExtCallee;
writeln("Entered: ", __FUNCTION__);
// I had to scope this to get it to compile
// If instead I put the function in myfn.d and
// did "import myfn;" it works without the scope operator.
ExtCallee.ExtCallee();
writeln("Exiting: ", __FUNCTION__);
}
```
Compile with:
$ dmd ExtCallee.d ExtMain.d -of=prog
Without extern(C), the linker mangles names:
$ nm ExtCallee.o | grep ExtCallee
0000000000000000 R _D9ExtCallee12__ModuleInfoZ
0000000000000000 W _D9ExtCalleeQkFZv
$ nm ExtMain.o | grep ExtCallee
U _D9ExtCalleeQkFZv
With extern(C), the linker does not mangle names:
$ nm ExtCallee.o | grep ExtCallee
0000000000000000 W ExtCallee
0000000000000000 R _D9ExtCallee12__ModuleInfoZ
$ nm ExtMain.o | grep ExtCallee
U ExtCallee
If not calling C code, why use extern(C) for D code?
scot
Apr 18 2023
On Tuesday, 18 April 2023 at 21:31:21 UTC, thinkunix wrote: [...]If not calling C code, why use extern(C) for D code?Wanted to test out options of calling D routine (possibly -betterC) from both C and (full) D.
Apr 18 2023
DLearner via Digitalmars-d-learn wrote:On Tuesday, 18 April 2023 at 21:31:21 UTC, thinkunix wrote: [...]OK, thanks.If not calling C code, why use extern(C) for D code?Wanted to test out options of calling D routine (possibly -betterC) from both C and (full) D.
Apr 18 2023









ag0aep6g <anonymous example.com> 