Thread overview
Undefined Reference calling D from C using static linking
Mar 23, 2017
data pulverizer
Mar 23, 2017
Nicholas Wilson
Mar 23, 2017
data pulverizer
Mar 23, 2017
Nicholas Wilson
Mar 23, 2017
data pulverizer
Mar 23, 2017
Nicholas Wilson
Mar 23, 2017
Jacob Carlborg
March 23, 2017
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

March 23, 2017
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.
March 23, 2017
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
```
March 23, 2017
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.
March 23, 2017
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
```


March 23, 2017
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.
March 23, 2017
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