www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Undefined Reference calling D from C using static linking

reply data pulverizer <data.pulverizer gmail.com> writes:
I am trying to call a D function from C. Here is the D code:

```
/* dcode.d */
extern (C) nothrow  nogc  system {
     double multNum(double x, double y)
     {
         return x*y;
     }
}
```

Then the C code:

```
/* ccode.c */
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

extern double multNum(double x, double y);

int main()
{
     printf("output: %f", multNum(3.0, 4.0));
     return 0;
}

```

Then I compile with:

```
ldc2 -c dcode.d
gcc -c ccode.c
gcc -o output ccode.o dcode.o
```

I get the error:

```
dcode.o: In function `ldc.register_dso':
dcode.d:(.text.ldc.register_dso+0x6e): undefined reference to 
`_d_dso_registry'
collect2: error: ld returned 1 exit status
```

Compiler versions:

```
$ ldc2 --version
LDC - the LLVM D compiler (1.1.0):
   based on DMD v2.071.2 and LLVM 3.9.1
   built with LDC - the LLVM D compiler (1.1.0)
   Default target: x86_64-unknown-linux-gnu
   Host CPU: ivybridge
   http://dlang.org - http://wiki.dlang.org/LDC

   Registered Targets:
     x86    - 32-bit X86: Pentium-Pro and above
     x86-64 - 64-bit X86: EM64T and AMD64

```

```
$ gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  
There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A 
PARTICULAR PURPOSE.
```

I would appreciate it if someone could point out my mistake. 
Thank you in advance
Mar 23 2017
parent reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Thursday, 23 March 2017 at 09:11:28 UTC, data pulverizer wrote:
 I am trying to call a D function from C. Here is the D code:

 ```
 /* dcode.d */
 extern (C) nothrow  nogc  system {
     double multNum(double x, double y)
     {
         return x*y;
     }
 }
 ```

 [...]
It has to do with module references to druntime stuff. You can either try adding a pragma(LDC_no_module_info); //I think it is spelled correctly. or you can use ldc to link and it will link druntime gcc ccode.c -c ldc2 dcode.d code.o I don't know how well that will work.
Mar 23 2017
parent reply data pulverizer <data.pulverizer gmail.com> writes:
On Thursday, 23 March 2017 at 10:16:22 UTC, Nicholas Wilson wrote:
 It has to do with module references to druntime stuff. You can 
 either try adding a

 pragma(LDC_no_module_info); //I think it is spelled correctly.

 or you can use ldc to link and it will link druntime

 gcc ccode.c -c
 ldc2 dcode.d code.o

 I don't know how well that will work.
Many thanks, I tried: ``` pragma(LDC_no_moduleinfo) // https://wiki.dlang.org/LDC-specific_language_changes#LDC_no_moduleinfo ``` which worked, your method of doing the final compilation using ldc2 (or dmd) also works :-) Is there a dmd equivalent for `pragma(LDC_no_module_info);`? Attempting the final compilation `gcc -o output ccode.o dcode.o` after the second stage compilation `dmd -c dcode.d` gives an error: ``` dcode.o: In function `_D5dcode7__arrayZ': dcode.d:(.text._D5dcode7__arrayZ+0x23): undefined reference to `_d_arraybounds' dcode.o: In function `_D5dcode8__assertFiZv': dcode.d:(.text._D5dcode8__assertFiZv+0x23): undefined reference to `_d_assert' dcode.o: In function `_D5dcode15__unittest_failFiZv': dcode.d:(.text._D5dcode15__unittest_failFiZv+0x23): undefined reference to `_d_unittest' dcode.o:(.text.d_dso_init[.data.d_dso_rec]+0x22): undefined reference to `_d_dso_registry' collect2: error: ld returned 1 exit status ``` ``` dmd --version DMD64 D Compiler v2.073.2 Copyright (c) 1999-2016 by Digital Mars written by Walter Bright ```
Mar 23 2017
parent reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Thursday, 23 March 2017 at 10:49:37 UTC, data pulverizer wrote:
 On Thursday, 23 March 2017 at 10:16:22 UTC, Nicholas Wilson 
 wrote:
 It has to do with module references to druntime stuff. You can 
 either try adding a

 pragma(LDC_no_module_info); //I think it is spelled correctly.

 or you can use ldc to link and it will link druntime

 gcc ccode.c -c
 ldc2 dcode.d code.o

 I don't know how well that will work.
Many thanks, I tried: ``` pragma(LDC_no_moduleinfo) // https://wiki.dlang.org/LDC-specific_language_changes#LDC_no_moduleinfo ``` which worked, your method of doing the final compilation using ldc2 (or dmd) also works :-) Is there a dmd equivalent for `pragma(LDC_no_module_info);`? Attempting the final compilation `gcc -o output ccode.o dcode.o` after the second stage compilation `dmd -c dcode.d` gives an error: ``` dcode.o: In function `_D5dcode7__arrayZ': dcode.d:(.text._D5dcode7__arrayZ+0x23): undefined reference to `_d_arraybounds' dcode.o: In function `_D5dcode8__assertFiZv': dcode.d:(.text._D5dcode8__assertFiZv+0x23): undefined reference to `_d_assert' dcode.o: In function `_D5dcode15__unittest_failFiZv': dcode.d:(.text._D5dcode15__unittest_failFiZv+0x23): undefined reference to `_d_unittest' dcode.o:(.text.d_dso_init[.data.d_dso_rec]+0x22): undefined reference to `_d_dso_registry' collect2: error: ld returned 1 exit status ``` ``` dmd --version DMD64 D Compiler v2.073.2 Copyright (c) 1999-2016 by Digital Mars written by Walter Bright ```
Those functions are the bounds checking function, the non unittest assert function, the unittest function an module initialisation function respectively. dmd -boundscheck=off -release should get rid of the first two, you didn't compile with -unittest so I'm not sure why the thord one is there at all. For _d_dso_registry all i can suggest is see what -betterC gets you.
Mar 23 2017
parent reply data pulverizer <data.pulverizer gmail.com> writes:
On Thursday, 23 March 2017 at 11:32:25 UTC, Nicholas Wilson wrote:
 On Thursday, 23 March 2017 at 10:49:37 UTC, data pulverizer 
 wrote:
 On Thursday, 23 March 2017 at 10:16:22 UTC, Nicholas Wilson 
 wrote:
 It has to do with module references to druntime stuff. You 
 can either try adding a

 pragma(LDC_no_module_info); //I think it is spelled correctly.

 or you can use ldc to link and it will link druntime

 gcc ccode.c -c
 ldc2 dcode.d code.o

 I don't know how well that will work.
Many thanks, I tried: ``` pragma(LDC_no_moduleinfo) // https://wiki.dlang.org/LDC-specific_language_changes#LDC_no_moduleinfo ``` which worked, your method of doing the final compilation using ldc2 (or dmd) also works :-) Is there a dmd equivalent for `pragma(LDC_no_module_info);`? Attempting the final compilation `gcc -o output ccode.o dcode.o` after the second stage compilation `dmd -c dcode.d` gives an error: ``` dcode.o: In function `_D5dcode7__arrayZ': dcode.d:(.text._D5dcode7__arrayZ+0x23): undefined reference to `_d_arraybounds' dcode.o: In function `_D5dcode8__assertFiZv': dcode.d:(.text._D5dcode8__assertFiZv+0x23): undefined reference to `_d_assert' dcode.o: In function `_D5dcode15__unittest_failFiZv': dcode.d:(.text._D5dcode15__unittest_failFiZv+0x23): undefined reference to `_d_unittest' dcode.o:(.text.d_dso_init[.data.d_dso_rec]+0x22): undefined reference to `_d_dso_registry' collect2: error: ld returned 1 exit status ``` ``` dmd --version DMD64 D Compiler v2.073.2 Copyright (c) 1999-2016 by Digital Mars written by Walter Bright ```
Those functions are the bounds checking function, the non unittest assert function, the unittest function an module initialisation function respectively. dmd -boundscheck=off -release should get rid of the first two, you didn't compile with -unittest so I'm not sure why the thord one is there at all. For _d_dso_registry all i can suggest is see what -betterC gets you.
I just compiled `dmd -c dcode.d -betterC -boundscheck=off` (-betterC probably makes -boundscheck=off irrelevant but I threw it in as a prayer) I am still getting: ``` dcode.o:(.text.d_dso_init[.data.d_dso_rec]+0x22): undefined reference to `_d_dso_registry' collect2: error: ld returned 1 exit status ```
Mar 23 2017
parent reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Thursday, 23 March 2017 at 12:06:14 UTC, data pulverizer wrote:
 On Thursday, 23 March 2017 at 11:32:25 UTC, Nicholas Wilson 
 wrote:
 On Thursday, 23 March 2017 at 10:49:37 UTC, data pulverizer 
 wrote:
 [...]
Those functions are the bounds checking function, the non unittest assert function, the unittest function an module initialisation function respectively. dmd -boundscheck=off -release should get rid of the first two, you didn't compile with -unittest so I'm not sure why the thord one is there at all. For _d_dso_registry all i can suggest is see what -betterC gets you.
I just compiled `dmd -c dcode.d -betterC -boundscheck=off` (-betterC probably makes -boundscheck=off irrelevant but I threw it in as a prayer) I am still getting: ``` dcode.o:(.text.d_dso_init[.data.d_dso_rec]+0x22): undefined reference to `_d_dso_registry' collect2: error: ld returned 1 exit status ```
Getting dmd to do the linking should work. You may wish to see what mir (github.com/libmir) does to build in it's "Better C" mode, so i'm sure it is possible, I just don't know the incantations, sorry. Perhaps someone else can help.
Mar 23 2017
parent Jacob Carlborg <doob me.com> writes:
On 2017-03-23 13:26, Nicholas Wilson wrote:

 Getting dmd to do the linking should work.
 You may wish to see what mir (github.com/libmir) does to build in it's
 "Better C" mode, so i'm sure it is possible, I just don't know the
 incantations, sorry. Perhaps someone else can help.
As an ugly workaround, you can defined the "_d_dso_registry" symbol yourself. To be sure, it should match the signature in the runtime. -- /Jacob Carlborg
Mar 23 2017