www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Using D libs in C

reply GreatEmerald <pastas4 gmail.com> writes:
Is it possible to write a static library in D and then use it in a program
written in C? I've found instructions about using DLLs here on the website,
but there is no mention about using static libraries instead.

Also, is it possible to use the same method on Linux, just with .a files
instead? Or .so for that matter?
Jan 16 2011
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Of course!

dstatic.d:
module dstatic;

extern(C):

int add(int x, int y)
{
    return x + y;
}

Then compile with:
dmd -lib dstatic.d

driver.c:
#include "stdio.h"

int main()
{
    printf("add(4, 5) = %d", add(4, 5));
}

dmc driver.c dstatic.lib

driver.exe
 add(4, 5) = 9
Jan 16 2011
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
The problem (on Windows), is that the static lib is in the OMF format,
and modern tools like VC or MinGW won't be able to read those, because
they use COFF instead. So you would have to convert from OMF to COFF.

But on Linux I think DMD uses the standard Linux object file format,
so I don't think there's issues there. (AFAIK).
Jan 16 2011
parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
On 01/16/2011 03:34 PM, Andrej Mitrovic wrote:
 The problem (on Windows), is that the static lib is in the OMF format,
 and modern tools like VC or MinGW won't be able to read those, because
 they use COFF instead. So you would have to convert from OMF to COFF.

 But on Linux I think DMD uses the standard Linux object file format,
 so I don't think there's issues there. (AFAIK).
http://www.digitalmars.com/d/archives/digitalmars/D/learn/d_and_c_21526.html it didn't work the last time I tried it
Jan 16 2011
next sibling parent Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
On 01/16/2011 05:04 PM, Ellery Newcomer wrote:
 On 01/16/2011 03:34 PM, Andrej Mitrovic wrote:
 The problem (on Windows), is that the static lib is in the OMF format,
 and modern tools like VC or MinGW won't be able to read those, because
 they use COFF instead. So you would have to convert from OMF to COFF.

 But on Linux I think DMD uses the standard Linux object file format,
 so I don't think there's issues there. (AFAIK).
http://www.digitalmars.com/d/archives/digitalmars/D/learn/d_and_c_21526.html it didn't work the last time I tried it
hmm. take out the __gshared int, and add -lib to the dmd command, and it does work..
Jan 16 2011
prev sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
I've just realized I didn't even prototype the function in the C
module. DMC doesn't warn about this, it seems. Not even with the -A
(ANSI C) flag. It won't even warn me when I prototype the function and
pass doubles instead of ints. Maybe I didn't enable all warnings?
(I've used: dmc -wc -v2 -A).
Jan 16 2011
parent reply GreatEmerald <pastas4 gmail.com> writes:
Ah, I see, thanks! I'll try that.

While I don't have a problem with using DMC, but others who are willing to join
my
project might have one... Right now I'm using MinGW, so it would definitely be
useful to know how to convert the libraries to the format it understands...
Though
from the looks of it people are having problems with that... coffimplib only
does
a COFF->OMF conversion, and not the other way round, right?
Jan 17 2011
parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 1/17/11, GreatEmerald <pastas4 gmail.com> wrote:
 Ah, I see, thanks! I'll try that.

 While I don't have a problem with using DMC, but others who are willing to
 join my
 project might have one... Right now I'm using MinGW, so it would definitely
 be
 useful to know how to convert the libraries to the format it understands...
 Though
 from the looks of it people are having problems with that... coffimplib only
 does
 a COFF->OMF conversion, and not the other way round, right?
There is no dedicated tool that can do it alone, but I think I've just figured out a way to do it, and I'll post it in the D general newsgroup.
Jan 17 2011
prev sibling next sibling parent reply Trass3r <un known.com> writes:
Also make sure you use globals properly if you use them (shared,  
__gshared, etc.)
Jan 17 2011
parent reply GreatEmerald <pastas4 gmail.com> writes:
All right, it worked, when the D side is this:

module techborg;
import std.c.stdio;

extern(C):
    shared int ResultD;

    int Process(int Value)
    {
        printf("You have sent the value: %d\n", Value);
        ResultD = (Value % 5);
        return ResultD;
    }

However, if I wanted to use printf() from std.stdio, dmc can't link
the library any more and complains about undefined symbols:
techborg.lib
 Warning 140: Library probably needs FIXLIB
techborg.lib(techborg)
 Error 42: Symbol Undefined _D3std5stdio12__ModuleInfoZ

Also, what was that solution you found for converting OMF->COFF? I
can't seem to find the post you mentioned.
Jan 18 2011
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 1/19/11, GreatEmerald <pastas4 gmail.com> wrote:
 All right, it worked, when the D side is this:

 module techborg;
 import std.c.stdio;

 extern(C):
     shared int ResultD;

     int Process(int Value)
     {
         printf("You have sent the value: %d\n", Value);
         ResultD = (Value % 5);
         return ResultD;
     }

 However, if I wanted to use printf() from std.stdio, dmc can't link
 the library any more and complains about undefined symbols:
 techborg.lib
  Warning 140: Library probably needs FIXLIB
 techborg.lib(techborg)
  Error 42: Symbol Undefined _D3std5stdio12__ModuleInfoZ

 Also, what was that solution you found for converting OMF->COFF? I
 can't seem to find the post you mentioned.
That's odd. stdio publicly imports std.c.stdio which publicly imports core.stdc.stdio, where printf is located. Maybe it's a linker bug.. My post was here, I'm not sure why it's not displayed: http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=127079
Jan 19 2011
parent GreatEmerald <pastas4 gmail.com> writes:
Hmm, not being able to use D function kinda defeats the purpose of using it in
the
first place. Ah well, let's see if people know more about this elsewhere.

Anyway, I'm trying to compile this under Linux now. DMD works brilliantly and I
get techborg.a file. I do this (using Debian x64):

$ gcc -m32 bioborg.c techborg.a

...and LD is being silly again. This is the error:

techborg.a(techborg.o): In function `no symbol':
techborg.d:(.text+0x8): undefined reference to `_Dmodule_ref'
techborg.a(techborg.o): In function `_D8techborg7__arrayZ':
techborg.d:(.text._D8techborg7__arrayZ+0xe): undefined reference to
`_d_array_bounds'
techborg.a(techborg.o): In function `_D8techborg8__assertFiZv':
techborg.d:(.text._D8techborg8__assertFiZv+0xe): undefined reference to
`_d_assertm'
techborg.a(techborg.o): In function `_D8techborg15__unittest_failFiZv':
techborg.d:(.text._D8techborg15__unittest_failFiZv+0xe): undefined reference to
`_d_unittestm'
collect2: ld returned 1 exit status

Any ideas here?
Jan 19 2011
prev sibling parent reply GreatEmerald <pastas4 gmail.com> writes:
All right, found out how to make it compile. There are two ways:

1) Using DMD for the D part, DMC for the C part and combining them. This is
the batch file I use for that:

dmd -c -lib dpart.d
dmc cpart.c dpart.lib phobos.lib

2) Using DMD for the D part, DMC for the C part, DMD for combining them again:

dmd -c -lib dpart.d
dmc -c cpart.c
dmd cpart.obj dpart.lib phobos.lib

The first method gives me a "FIXLIB" warning but compiles OK, the second is
nicely silent, thus I prefer the second one. Plus it should work in Linux as
well. I'm going to try that shortly.
Feb 06 2011
next sibling parent reply GreatEmerald <pastas4 gmail.com> writes:
Hmm, no, it won't work right on Linux for some reason. This is the output:

/usr/lib/gcc/x86_64-linux-gnu/4.3.2/../../../libphobos2.a(deh2_4e7_525.o): In
function `_D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable':
src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x4):
undefined reference to `_deh_beg'
src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0xc):
undefined reference to `_deh_beg'
src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x13):
undefined reference to `_deh_end'
src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x37):
undefined reference to `_deh_end'
collect2: ld returned 1 exit status
--- errorlevel 1

The shell script I'm using to compile it is:

#!/bin/sh
dmd -m32 -c -lib dpart.d
gcc -m32 -c cpart.c
dmd -m32 cpart.o dpart.a /usr/lib/libphobos2.a

(Although it appears that you don't need to explicitly link with libphobos2, it
does it automatically... and fails with the above error.) Any ideas about what
the
error means?
Feb 06 2011
parent reply spir <denis.spir gmail.com> writes:
On 02/07/2011 07:53 AM, GreatEmerald wrote:
 Hmm, no, it won't work right on Linux for some reason. This is the output:

 /usr/lib/gcc/x86_64-linux-gnu/4.3.2/../../../libphobos2.a(deh2_4e7_525.o): In
 function `_D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable':
 src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x4):
 undefined reference to `_deh_beg'
 src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0xc):
 undefined reference to `_deh_beg'
 src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x13):
 undefined reference to `_deh_end'
 src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x37):
 undefined reference to `_deh_end'
 collect2: ld returned 1 exit status
 --- errorlevel 1

 The shell script I'm using to compile it is:

 #!/bin/sh
 dmd -m32 -c -lib dpart.d
 gcc -m32 -c cpart.c
 dmd -m32 cpart.o dpart.a /usr/lib/libphobos2.a

 (Although it appears that you don't need to explicitly link with libphobos2, it
 does it automatically... and fails with the above error.) Any ideas about what
the
 error means?
Take my words with much doubt, I've few exp in that. Are you sure you did use same source under both OSes? "undefined reference to `_deh_end' / `_deh_beg'" (read: "D-begin" / "D-end" I guess, looks like Pascal slang ;-) is nicely output by the linker when your "main" module does not have a main(). (There is a similar error when an imported module has a main(), eg for testing, so that the linker finds 2 of them.) Did you change something before compiling under Linux? Or does this pseudo-error happen only under Linux? Add an empty main() to your top module, and tell us... Denis -- _________________ vita es estrany spir.wikidot.com
Feb 07 2011
next sibling parent reply GreatEmerald <pastas4 gmail.com> writes:
Everything is right from what I can tell. This is the code I use for the D part:

module dpart;
import std.c.stdio;

extern(C):

    shared int ResultD;

    int Process(int Value)
    {
        printf("You have sent the value: %d\n", Value);
        ResultD = (Value % 5);
        return ResultD;
    }

And the C part:

#include <stdio.h>
extern int ResultD;
int Process(int Value);

int main()
{
	printf("Sending 3...\n");
	Process(3);
	printf("The result is %d\n", ResultD);
	getchar();
	return 0;
}

This is pretty much the same thing as in the Windows version, just with scanf()
omitted.

Jacob, in Windows I am required to explicitly tell DMD to compile phobos.lib,
but
not in Linux. Quite odd.
Feb 07 2011
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 2/7/11, GreatEmerald <pastas4 gmail.com> wrote:
in Windows I am required to explicitly tell DMD to compile
 phobos.lib, but
 not in Linux. Quite odd.
Check the sc.ini file in dmd/windows/bin, make sure it has at least this for the LIB variable: LIB="% P%\..\lib";
Feb 07 2011
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 07 Feb 2011 10:28:41 -0500, GreatEmerald <pastas4 gmail.com> wrote:

 Everything is right from what I can tell. This is the code I use for the  
 D part:

 module dpart;
 import std.c.stdio;

 extern(C):

     shared int ResultD;

     int Process(int Value)
     {
         printf("You have sent the value: %d\n", Value);
         ResultD = (Value % 5);
         return ResultD;
     }

 And the C part:

 #include <stdio.h>
 extern int ResultD;
 int Process(int Value);

 int main()
 {
 	printf("Sending 3...\n");
 	Process(3);
 	printf("The result is %d\n", ResultD);
 	getchar();
 	return 0;
 }

 This is pretty much the same thing as in the Windows version, just with  
 scanf()
 omitted.

 Jacob, in Windows I am required to explicitly tell DMD to compile  
 phobos.lib, but
 not in Linux. Quite odd.
The issue is that you are not calling the D runtime initialization code. This is required in order to get D working properly. See the C main function in druntime here: https://github.com/D-Programming-Language/druntime/blob/master/src/rt/dmain2.d#L335 Basically, you are going to have to duplicate the runtime startup code. I'm not sure it will work properly. People typically run main from D and call their C functions from there. This is also certainly an option. The errors you are getting are link errors. I'm guessing that maybe because you aren't calling the d runtime, the linker is opimizing out the deh code early on, but then needs it again later? Not sure. -Steve
Feb 07 2011
parent reply GreatEmerald <pastas4 gmail.com> writes:
OK, well this is interesting... I managed to compile it but it's quite odd. In
order to do that, I added a call to main() in my Process() function, and then
added an empty main() in the D part before "extern(C)". It seems that there are
no
conflicts, too.

Andrej, that line is there. But it really doesn't matter, it's not like adding
one
word to the command line is hard.
Feb 07 2011
parent spir <denis.spir gmail.com> writes:
On 02/07/2011 06:41 PM, GreatEmerald wrote:
 OK, well this is interesting... I managed to compile it but it's quite odd. In
 order to do that, I added a call to main() in my Process() function, and then
 added an empty main() in the D part before "extern(C)". It seems that there
are no
 conflicts, too.
That's it, I guess; you always need a main(), even if empty {}, somewhere. I routinely add that in every module (part of my template code), if only for running test code, and comment it out when the module is /actually/ imported. I consider this as a minor design error. Denis -- _________________ vita es estrany spir.wikidot.com
Feb 07 2011
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 07 Feb 2011 06:42:46 -0500, spir <denis.spir gmail.com> wrote:

 On 02/07/2011 07:53 AM, GreatEmerald wrote:
 Hmm, no, it won't work right on Linux for some reason. This is the  
 output:

 /usr/lib/gcc/x86_64-linux-gnu/4.3.2/../../../libphobos2.a(deh2_4e7_525.o):  
 In
 function `_D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable':
 src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x4):
 undefined reference to `_deh_beg'
 src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0xc):
 undefined reference to `_deh_beg'
 src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x13):
 undefined reference to `_deh_end'
 src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x37):
 undefined reference to `_deh_end'
 collect2: ld returned 1 exit status
 --- errorlevel 1

 The shell script I'm using to compile it is:

 #!/bin/sh
 dmd -m32 -c -lib dpart.d
 gcc -m32 -c cpart.c
 dmd -m32 cpart.o dpart.a /usr/lib/libphobos2.a

 (Although it appears that you don't need to explicitly link with  
 libphobos2, it
 does it automatically... and fails with the above error.) Any ideas  
 about what the
 error means?
Take my words with much doubt, I've few exp in that. Are you sure you did use same source under both OSes? "undefined reference to `_deh_end' / `_deh_beg'"
deh == d exception handling (or handler, not sure) ;) Looks like the module that's failing to link is rt.deh -Steve
Feb 07 2011
parent reply spir <denis.spir gmail.com> writes:
On 02/07/2011 04:32 PM, Steven Schveighoffer wrote:
 On Mon, 07 Feb 2011 06:42:46 -0500, spir <denis.spir gmail.com> wrote:

 On 02/07/2011 07:53 AM, GreatEmerald wrote:
 Hmm, no, it won't work right on Linux for some reason. This is the output:

 /usr/lib/gcc/x86_64-linux-gnu/4.3.2/../../../libphobos2.a(deh2_4e7_525.o): In
 function `_D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable':
 src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x4):

 undefined reference to `_deh_beg'
 src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0xc):

 undefined reference to `_deh_beg'
 src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x13):

 undefined reference to `_deh_end'
 src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x37):

 undefined reference to `_deh_end'
 collect2: ld returned 1 exit status
 --- errorlevel 1

 The shell script I'm using to compile it is:

 #!/bin/sh
 dmd -m32 -c -lib dpart.d
 gcc -m32 -c cpart.c
 dmd -m32 cpart.o dpart.a /usr/lib/libphobos2.a

 (Although it appears that you don't need to explicitly link with libphobos2, it
 does it automatically... and fails with the above error.) Any ideas about
 what the
 error means?
Take my words with much doubt, I've few exp in that. Are you sure you did use same source under both OSes? "undefined reference to `_deh_end' / `_deh_beg'"
deh == d exception handling (or handler, not sure) ;) Looks like the module that's failing to link is rt.deh
Are you sure of that? I get exactly the same kind of linker error when forgetting a fake main(){} (whatver the number of modules). Eg: ... src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh21 DHandlerTable+0xc): undefined reference to `_deh_beg' src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213 HandlerTable+0x13): undefined reference to `_deh_end' ... repeted n times. Denis -- _________________ vita es estrany spir.wikidot.com
Feb 07 2011
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 07 Feb 2011 13:53:14 -0500, spir <denis.spir gmail.com> wrote:

 On 02/07/2011 04:32 PM, Steven Schveighoffer wrote:
 On Mon, 07 Feb 2011 06:42:46 -0500, spir <denis.spir gmail.com> wrote:

 On 02/07/2011 07:53 AM, GreatEmerald wrote:
 Hmm, no, it won't work right on Linux for some reason. This is the  
 output:

 /usr/lib/gcc/x86_64-linux-gnu/4.3.2/../../../libphobos2.a(deh2_4e7_525.o):  
 In
 function `_D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable':
 src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x4):

 undefined reference to `_deh_beg'
 src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0xc):

 undefined reference to `_deh_beg'
 src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x13):

 undefined reference to `_deh_end'
 src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x37):

 undefined reference to `_deh_end'
 collect2: ld returned 1 exit status
 --- errorlevel 1

 The shell script I'm using to compile it is:

 #!/bin/sh
 dmd -m32 -c -lib dpart.d
 gcc -m32 -c cpart.c
 dmd -m32 cpart.o dpart.a /usr/lib/libphobos2.a

 (Although it appears that you don't need to explicitly link with  
 libphobos2, it
 does it automatically... and fails with the above error.) Any ideas  
 about
 what the
 error means?
Take my words with much doubt, I've few exp in that. Are you sure you did use same source under both OSes? "undefined reference to `_deh_end' / `_deh_beg'"
deh == d exception handling (or handler, not sure) ;) Looks like the module that's failing to link is rt.deh
Are you sure of that? I get exactly the same kind of linker error when forgetting a fake main(){} (whatver the number of modules). Eg: ... src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh21 DHandlerTable+0xc): undefined reference to `_deh_beg' src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213 HandlerTable+0x13): undefined reference to `_deh_end' ... repeted n times.
Hm... it looks like _deh_beg and _deh_end is something defined by the compiler? It's used in deh2.d but not defined anywhere in druntime. I'm pretty sure deh stands for d exception handler. -Steve
Feb 07 2011
parent reply Jacob Carlborg <doob me.com> writes:
On 2011-02-07 20:07, Steven Schveighoffer wrote:
 On Mon, 07 Feb 2011 13:53:14 -0500, spir <denis.spir gmail.com> wrote:

 On 02/07/2011 04:32 PM, Steven Schveighoffer wrote:
 On Mon, 07 Feb 2011 06:42:46 -0500, spir <denis.spir gmail.com> wrote:

 On 02/07/2011 07:53 AM, GreatEmerald wrote:
 Hmm, no, it won't work right on Linux for some reason. This is the
 output:

 /usr/lib/gcc/x86_64-linux-gnu/4.3.2/../../../libphobos2.a(deh2_4e7_525.o):
 In
 function `_D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable':
 src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x4):


 undefined reference to `_deh_beg'
 src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0xc):


 undefined reference to `_deh_beg'
 src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x13):


 undefined reference to `_deh_end'
 src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x37):


 undefined reference to `_deh_end'
 collect2: ld returned 1 exit status
 --- errorlevel 1

 The shell script I'm using to compile it is:

 #!/bin/sh
 dmd -m32 -c -lib dpart.d
 gcc -m32 -c cpart.c
 dmd -m32 cpart.o dpart.a /usr/lib/libphobos2.a

 (Although it appears that you don't need to explicitly link with
 libphobos2, it
 does it automatically... and fails with the above error.) Any ideas
 about
 what the
 error means?
Take my words with much doubt, I've few exp in that. Are you sure you did use same source under both OSes? "undefined reference to `_deh_end' / `_deh_beg'"
deh == d exception handling (or handler, not sure) ;) Looks like the module that's failing to link is rt.deh
Are you sure of that? I get exactly the same kind of linker error when forgetting a fake main(){} (whatver the number of modules). Eg: ... src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0xc): undefined reference to `_deh_beg' src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x13): undefined reference to `_deh_end' ... repeted n times.
Hm... it looks like _deh_beg and _deh_end is something defined by the compiler? It's used in deh2.d but not defined anywhere in druntime. I'm pretty sure deh stands for d exception handler. -Steve
The compiler puts this in the binary. -- /Jacob Carlborg
Feb 08 2011
next sibling parent "Dainius (GreatEmerald)" <pastas4 gmail.com> writes:
Now I'm trying to do something more complicated, and it seems that while
importing works (it compiles and links fine), actually using the imported
things or pretty much anything that D offers makes the program crash. For
instance, in the D part:

-------------------
module dpart;
import std.stdio;

version(linux)
{
    int main()
    {
        return 0;
    }
}

extern(C):
shared int ResultD;

int Process(int Value)
{
    writeln("hai"); //<- Hangs here
    printf("You have sent the value %d to the D library.\n", Value);
    ResultD = (Value % 5);
    string a; //Doesn't hang
    a = "10";//Doesn't hang
    printf("String %s", a); //<- Hangs here
    return ResultD;
}
-------------------

There is no readable error, just your ordinary program crash "report this to
Microsoft"... Any idea why it's like that?
Mar 20 2011
prev sibling parent reply "Dainius (GreatEmerald)" <pastas4 gmail.com> writes:
I've tried compiling the same on Linux and the program still crashes
(with segmentation fault there). No error message or anything. And it
doesn't matter if I compile the thing from .obj or from .lib files, I
still get the same crashes. So it's a real showtopper for me, since
what's the use of having static libraries that compile successfully
yet crash every time you attempt to use them?..

Anyone have any ideas about what's happening? Or should I just go
ahead and submit this to the bug tracker?
Mar 22 2011
parent reply Daniel Green <venix1 gmail.com> writes:
On 3/22/2011 6:46 PM, Dainius (GreatEmerald) wrote:
 I've tried compiling the same on Linux and the program still crashes
 (with segmentation fault there). No error message or anything. And it
 doesn't matter if I compile the thing from .obj or from .lib files, I
 still get the same crashes. So it's a real showtopper for me, since
 what's the use of having static libraries that compile successfully
 yet crash every time you attempt to use them?..

 Anyone have any ideas about what's happening? Or should I just go
 ahead and submit this to the bug tracker?
The D runtime needs to be initialized. Call rt_init before using your library and rt_term when your done with it. The D runtime replaces main with initialization code and renames the programs main to _Dmain. extern (C) bool rt_init( void delegate( Exception ) dg = null ); extern (C) bool rt_term( void delegate( Exception ) dg = null );
Mar 22 2011
parent reply "Dainius (GreatEmerald)" <pastas4 gmail.com> writes:
Ooh, thanks, it works! Though linking in Linux is still quite odd. So
the final code for my test program is this:

==== cpart.c ====
#include <stdio.h>

extern int ResultD;

int Process(int Value);
int rt_init();
int rt_term();
void LinuxInit();

int main()
{
	int num;
	
	rt_init(); //Init D library
	LinuxInit(); //Code for linking in Linux
	
	printf("Enter a number\n");
	scanf("%d", &num);
	Process(num);
	printf("The result is %d\n", ResultD);
	getchar();
	
	rt_term(); //Terminate D library
}

==== dpart.d ====
module dpart;
import std.stdio;

version(linux)
	int main() { return 0; }
extern (C) bool  rt_init( void delegate( Exception ) dg = null );
extern (C) bool  rt_term( void delegate( Exception ) dg = null );

extern(C):
	shared int ResultD;

	int Process(int Value)
	{
		writeln("You have sent the value: ", Value);
		ResultD = (Value % 5);
		return ResultD;
	}

	void LinuxInit()
	{
		version(linux)
			main();
	}

==== commands to compile ====
On Linux:
dmd -m32 -c -lib dpart.d
gcc -m32 -c cpart.c
dmd -m32 cpart.o dpart.a /usr/lib/libphobos2.a

On Windows:
dmd -c -lib dpart.d
dmc -c cpart.c
dmd cpart.obj dpart.lib phobos.lib
Or:
dmd -lib dpart.d
dmc cpart.c dpart.lib C:\D\dmd2\windows\lib\phobos.lib


Though I find it quite odd that I need workarounds like those to
compile on Linux, but ah well, it works, at least. Also odd that I
can't link using GCC on Linux, it gives me a long list of undefined
references (it seems that they are all coming from phobos2, it's here
if you wish to look through it: http://pastebin.com/cfyMDzDn ). But
once again, at least it works now, so thanks a lot!
Mar 23 2011
parent reply Daniel Green <venix1 gmail.com> writes:
On 3/23/2011 3:22 AM, Dainius (GreatEmerald) wrote:
 Though I find it quite odd that I need workarounds like those to
 compile on Linux, but ah well, it works, at least. Also odd that I
 can't link using GCC on Linux, it gives me a long list of undefined
 references (it seems that they are all coming from phobos2, it's here
 if you wish to look through it: http://pastebin.com/cfyMDzDn ). But
 once again, at least it works now, so thanks a lot!
The weird linking with Linux appears to be caused by DMD requiring symbols for thread local storage. When you declare main, DMD will output those symbols. I don't know of any other way to get those symbols. int function() _main = &main; // Makes DMD output the _tls symbols. Your issue when linking with GCC looks like your missing the pthread library or development files. gcc cpart.o -o cpart -m32 -Xlinker -L/home/venix/dmd2/linux/bin/../lib32 -Xlinker -L/home/venix/dmd2/linux/bin/../lib64 -Xlinker --no-warn-search-mismatch -Xlinker --export-dynamic -lrt dpart.a -lphobos2 **-lpthread** -lm Something a little more cosmetic, would be to have the D library call rt_init and rt_term. That could be automatic with a shared library. With a static library having Library_Init and Library_Quit do it would work.
Mar 23 2011
parent reply "Dainius (GreatEmerald)" <pastas4 gmail.com> writes:
Ah, including pthread indeed works, but now I've run into another
problem related to Linux and architecture. I want to use D for my
program that also uses things like SDL and Lua. Earlier when I
compiled it, I always did so with 64-bit libraries. But D is so far
only in 32-bits, thus when compiling it doesn't accept phobos2. And it
also seems that Debian x64 (which I'm using to compile this at the
moment) doesn't have 32-bit libs of SDL as well. Plus compiling SDL
from source doesn't work either. So how should I proceed with this?
Try to get the beta D x64 libraries?
Mar 24 2011
parent reply Jesse Phillips <jessekphillips+D gmail.com> writes:
Dainius (GreatEmerald) Wrote:

 Ah, including pthread indeed works, but now I've run into another
 problem related to Linux and architecture. I want to use D for my
 program that also uses things like SDL and Lua. Earlier when I
 compiled it, I always did so with 64-bit libraries. But D is so far
 only in 32-bits, thus when compiling it doesn't accept phobos2. And it
 also seems that Debian x64 (which I'm using to compile this at the
 moment) doesn't have 32-bit libs of SDL as well. Plus compiling SDL
 from source doesn't work either. So how should I proceed with this?
 Try to get the beta D x64 libraries?
Assuming it isn't Production Critical, use -m64 flag in DMD. You shouldn't need to "get" the libraries as they come with dmd 2.052. The generated 64 bit might be buggy, but people need to start using it so bugs can be found.
Mar 24 2011
next sibling parent "Dainius (GreatEmerald)" <pastas4 gmail.com> writes:
Hmm... Spent a few hours trying to figure out how to update GCC and
all to conform to the requirements for 2.0.52, and at seems that it
compiles my small test program just fine, but it fails on compiling
the main project for some reason. And the linker outputs
half-scrambled things. Anyway, here's all the output that shows how
I'm trying to build the thing:
http://pastebin.com/j7bE76bn
It seems that it for some odd reason doesn't want to link the imports,
and I don't see why is that, since my small test program works, and it
uses basically the same thing...
Mar 24 2011
prev sibling next sibling parent "Dainius (GreatEmerald)" <pastas4 gmail.com> writes:
Oh, I found the problem... It's just me forgetting that my library has
to go before phobos to compile it. So right now it works perfectly!
Thanks!
Mar 25 2011
prev sibling parent reply "Dainius (GreatEmerald)" <pastas4 gmail.com> writes:
OK, now I have a question about passing variables. In D, I have a
dynamic array of strings and I want C to get that array. Yet C
supports neither dynamic arrays nor strings. So is there a way to
accomplish this?
Mar 27 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Dainius (GreatEmerald):

 OK, now I have a question about passing variables. In D, I have a
 dynamic array of strings and I want C to get that array. Yet C
 supports neither dynamic arrays nor strings. So is there a way to
 accomplish this?
To use a D data structure from C you need first of all to know what exactly those data structures are. In this case one solution is to create (from D) a dynamic array of char*, then perform a map!toStringz to convert the strings to C strings, and then call the C code with the ptr and length of this dynamic array of pointers. There are other solutions, according to the amount of data you want to copy or according to the amount of C code you want to write to access the D data structures. Bye, bearophile
Mar 27 2011
parent reply "Dainius (GreatEmerald)" <pastas4 gmail.com> writes:
Well, the situation is like this: D creates a list of names of files
that should be loaded by C. C then takes the list, uses it to load the
files, then stores both the pointers to the loaded files and the names
of the files in an array of structs. Then when C wants to access the
files, it asks D about which file to access, which then sends the file
name, and C compares the known file names and on finding a match,
accesses the file.
So that means that the array should be pretty much read-only there,
but C needs to know how big the newly created array of structs has to
be. As for how long the list of file names will be - it's determined
by the configuration, so it will be anywhere from 1 to around 300 or
even more.
Mar 27 2011
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Dainius (GreatEmerald):

 Well, the situation is like this: D creates a list of names of files
 that should be loaded by C. C then takes the list, uses it to load the
 files, then stores both the pointers to the loaded files and the names
 of the files in an array of structs. Then when C wants to access the
 files, it asks D about which file to access, which then sends the file
 name, and C compares the known file names and on finding a match,
 accesses the file.
 So that means that the array should be pretty much read-only there,
 but C needs to know how big the newly created array of structs has to
 be. As for how long the list of file names will be - it's determined
 by the configuration, so it will be anywhere from 1 to around 300 or
 even more.
So? Bye, bearophile
Mar 27 2011
prev sibling parent reply Jesse Phillips <jessekphillips+D gmail.com> writes:
Dainius (GreatEmerald) Wrote:

 Well, the situation is like this: D creates a list of names of files
 that should be loaded by C. C then takes the list, uses it to load the
 files, then stores both the pointers to the loaded files and the names
 of the files in an array of structs. Then when C wants to access the
 files, it asks D about which file to access, which then sends the file
 name, and C compares the known file names and on finding a match,
 accesses the file.
 So that means that the array should be pretty much read-only there,
 but C needs to know how big the newly created array of structs has to
 be. As for how long the list of file names will be - it's determined
 by the configuration, so it will be anywhere from 1 to around 300 or
 even more.
If you want to pass an array of file names to C, you must pass it as a char**, accomplished as bearophile has stated. Since your C program is asking D which files to work with next why doesn't it load the file at that time? If the file is processed multiple times, you can still cache the data and just check if it is already cached.
Mar 27 2011
next sibling parent "Dainius (GreatEmerald)" <pastas4 gmail.com> writes:
Hmm, if I was to do it from C, I would have to deal with all the
allocation, since I don't know how large the array is going to be when
it's complete, while D doesn't need to know since it uses dynamic
arrays.
Mar 27 2011
prev sibling next sibling parent "Dainius (GreatEmerald)" <pastas4 gmail.com> writes:
All right, I solved that part of the problem by creating a linked
list. However, getting the string out of D is still problematic,
namely because toStringz() gives me an immutable char*, and I don't
seem to be able to pass those, since I can't assign those to immutable
variables outside their constructors. Also, if I use this:
//D:
void GetString()
{
    ReceiveString(toStringz(StringD));
}

//C:
extern(C) void ReceiveString(char* String)
{
    StringC = String;
}

DMD gives me "Error: undefined identifier ReceiveString" for some reason.
Mar 29 2011
prev sibling next sibling parent "Dainius (GreatEmerald)" <pastas4 gmail.com> writes:
Oh, never mind. About sending strings, I got it working, I just had to
create a function like this in D:

immutable(char)* GetString()
{
    return StringD.toStringz();
}

As for D not compiling, I had to declare it in D, d'oh :D And that
extern is in the wrong place there.
Mar 29 2011
prev sibling next sibling parent "Dainius (GreatEmerald)" <pastas4 gmail.com> writes:
All right, found something really odd today, might be a bug. If in C I
have this:

int16_t D_getPictureCoordX(int Pool, int Card);

And in D I have this:

short D_getPictureCoordX(int Pool, int Card);

When I call D_getPictureCoord() from C, the parameters are all off, it
seems that it receives either a random memory bit or the parameters
are not in the same order as they should be. However, this only
happens in Linux using 64-bit DMD, on Windows it works just fine.
Apr 15 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
AFAIK 'int' in D is always a 32-bit value. But in C, 'int' could be
64bit on 64bit platforms. You could try printing sizeof(int) in C and
compare that to int.sizeof in D and see if they match. You probably
know this, but make sure your exported D function is annotated with
extern(C).
Apr 15 2011
prev sibling parent "Dainius (GreatEmerald)" <pastas4 gmail.com> writes:
They both return 4, and both short and int16_t return 2.
Also, I've noticed that if I use a struct (of four ints) instead, the
same thing happens, the parameters are not correct. And yes, of course
they are extern already.
Apr 15 2011
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2011-02-07 07:32, GreatEmerald wrote:
 All right, found out how to make it compile. There are two ways:

 1) Using DMD for the D part, DMC for the C part and combining them. This is
 the batch file I use for that:

 dmd -c -lib dpart.d
 dmc cpart.c dpart.lib phobos.lib

 2) Using DMD for the D part, DMC for the C part, DMD for combining them again:

 dmd -c -lib dpart.d
 dmc -c cpart.c
 dmd cpart.obj dpart.lib phobos.lib

 The first method gives me a "FIXLIB" warning but compiles OK, the second is
 nicely silent, thus I prefer the second one. Plus it should work in Linux as
 well. I'm going to try that shortly.
I would recommend always linking with dmd, then you want need to link any D specifics, like phobos. -- /Jacob Carlborg
Feb 07 2011