Bug 6716 – Linking a C program with D library causes DEH errors
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2011-09-22T12:02:00Z
Last change time
2017-01-16T23:24:36Z
Keywords
pull
Assigned to
nobody
Creator
pastas4
Comments
Comment #0 by pastas4 — 2011-09-22T12:02:32Z
This is a pretty specific bug in that it happens only on Linux ld, and has a pretty specific workaround. If we have two files, a D library like this:
-----------
module lib;
import std.stdio;
extern (C):
void libraryFunction()
{
writeln("Hello library world!");
}
-----------
And a C executable like this:
-----------
#include <stdio.h>
int main()
{
rt_init();
libraryFunction();
rt_term();
printf("Hello executable world!");
getchar();
return 0;
}
-----------
They will not link properly. These are the commands used:
-----------
dmd -lib lib.d
gcc -c bin.c
dmd bin.o lib.a
-----------
The linker errors are these (skipped duplicates):
-----------
src/core/thread.d:(.text._D4core6thread6Thread6__ctorMFPFZvmZC4core6thread6Thread+0x2b): undefined reference to `_tlsend'
src/core/thread.d:(.text._D4core6thread6Thread6__ctorMFPFZvmZC4core6thread6Thread+0x36): undefined reference to `_tlsstart'
src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0xa): undefined reference to `_deh_beg'
src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x1e): undefined reference to `_deh_end'
src/rt/lifetime.d:(.text._D2rt8lifetime18_sharedStaticCtor9FZv+0x15): undefined reference to `_tlsend'
src/rt/lifetime.d:(.text._D2rt8lifetime18_sharedStaticCtor9FZv+0x29): undefined reference to `_tlsstart'
-----------
In order to work around the problem, you have to define a main() function that is not extern(C) and that gets called from an extern(C) function at some point. That makes the D library file look like this:
-----------
module lib;
import std.stdio;
void main(){}
extern (C):
void libraryFunction()
{
main();
writeln("Hello library world!");
}
-----------
Naturally, the downside of this method is that you can no longer use such library with D executables, since a redundancy is created by two conflicting definitions of main(). And the only way to work around the latter problem so far is to use a version(identifier) system...
Comment #1 by verylonglogin.reg — 2012-09-12T21:47:15Z
> In order to work around the problem, you have to define a main() function that
> is not extern(C) and that gets called from an extern(C) function at some point.
No, you don't need to call D `main` function. You just have to define it.
> Naturally, the downside of this method is that you can no longer use such
> library with D executables, since a redundancy is created by two conflicting
> definitions of main(). And the only way to work around the latter problem so
> far is to use a version(identifier) system...
No, you can define D `main` in a separate file, not in your library and link with its object file. For more information read this:
http://stackoverflow.com/questions/7480046/implementing-a-c-api-in-d/7486417#7486417