Calling C functions

Steven Schveighoffer schveiguy at yahoo.com
Thu Dec 9 08:28:06 PST 2010


On Thu, 09 Dec 2010 10:15:59 -0500, CrypticMetaphor  
<CrypticMetaphor88 at gmail.com> wrote:

> On 12/9/2010 3:57 PM, Steven Schveighoffer wrote:
>> On Thu, 09 Dec 2010 09:37:03 -0500, CrypticMetaphor
>> <CrypticMetaphor88 at gmail.com> wrote:
>>
>>> I found this page that describes how to call c functions from D.
>>>
>>> I found this page that describes how:
>>> http://arsdnet.net/dtips/#cfunc
>>>
>>> on that page he uses gcc, and I use dmc, but I get different results.
>>> This is what I did
>>>
>>> // cfile.c file
>>> extern int globalFromD;
>>>
>>> void functionFromC(int a) {
>>> globalFromD = a;
>>> }
>>> // end cfile.c
>>>
>>> // dfile.d
>>> extern(C) { // this is needed to make it available from C
>>> int globalFromD;
>>> }
>>> extern(C) { // also needed when listing the prototypes for your C
>>> functions
>>> void functionFromC(int);
>>> }
>>>
>>> import std.stdio; // for writefln
>>>
>>> int main() {
>>> globalFromD = 100;
>>> writefln("%d", globalFromD);
>>>
>>> functionFromC(500);
>>> writefln("%d", globalFromD);
>>>
>>> return 0;
>>> }
>>> // end dfile.d
>>>
>>> I compile with:
>>> dmc -c cfile.c
>>> And I get an cfile.obj, which is the object code (.o in gcc).
>>> Then I compile the D code
>>> dmd dfile.d cfile.obj
>>> and I get no errors, so I run it, the result:
>>> // start result
>>> C:\DCode\libtest>dfile.exe
>>> 100
>>> 100
>>>
>>> C:\DCode\libtest>
>>> // end result
>>>
>>> Why is it still 100? It should be 500. I don't think functionFromC(
>>> int ) is being called, and I can't really find any other sources that
>>> clearly explain how to do this simple stuff, so can anyone explain how
>>> to fix it?
>>
>> I'm guessing that this is a later D2 compiler? If so, then the default
>> storage for globals is in Thread Local Storage (local to each thread).
>> This could explain why it doesn't work, because globalFromD is in TLS in
>> D-land, but in the normal global space in C-land. But there is no
>> declaration of the global-space version then, so I'm surprised it would
>> compile then.
>>
>> I'm really curious why this doesn't work but does compile.
>>
>> What version of D compiler are you using?
>>
>> When using dmd 2.050 on linux I get this error when compiling:
>>
>> steves at steve-laptop:~/testd$ gcc -c testc.c
>> steves at steve-laptop:~/testd$ ~/dmd-2.050/linux/bin/dmd testcallc.d  
>> testc.o
>> /usr/bin/ld: globalFromD: TLS definition in testcallc.o section .tbss
>> mismatches non-TLS reference in testc.o
>> testc.o: could not read symbols: Bad value
>> collect2: ld returned 1 exit status
>> --- errorlevel 1
>>
>> Maybe it's a bug in Windows dmd?
>>
>> -Steve
>
> Yeah I am using D2
>
> dmc version: 8.42n
> dmd version: 2.050
>
> Windows XP. But yeah, it compiles
>
> here is a screenshot:
> http://img813.imageshack.us/img813/8230/testu.gif
>
> So I gotta read more about threads eh? But that's all the way at the end  
> of the book :-(

No, not really.  TLS is related to threads, but you don't really have to  
understand how threads work to understand where things are stored.

I don't know where it is in the book, but try looking for Thread Local  
Storage in the index?

> But anyway, it should not compile right?
>
> Should I submit a bug report or something?

Yes please, and be sure to specify that it correctly does not compile on  
linux. http://d.puremagic.com/issues/enter_bug.cgi

> And how I supposed to call the c function?

Mark the extern(C) integer as __gshared in D.  That will put it in the  
global namespace instead of TLS.

e.g.:

extern(C) { // this is needed to make it available from C
   __gshared int globalFromD;
}

-Steve


More information about the Digitalmars-d-learn mailing list