digitalmars.D.learn - Calling C functions
- CrypticMetaphor (43/43) Dec 09 2010 I found this page that describes how to call c functions from D.
- Steven Schveighoffer (20/64) Dec 09 2010 I'm guessing that this is a later D2 compiler? If so, then the default ...
- CrypticMetaphor (12/88) Dec 09 2010 Yeah I am using D2
- Steven Schveighoffer (15/112) Dec 09 2010 No, not really. TLS is related to threads, but you don't really have to...
- Andrej Mitrovic (7/125) Dec 09 2010 I know I prefer using shared() when interfacing with C.
- Steven Schveighoffer (15/34) Dec 09 2010 __gshared is the equivalent of what normal globals used to be (in D1 and...
- Andrej Mitrovic (30/33) Dec 09 2010 My dev PC is in repairs right now so I don't have the code atm. It's a
- Steven Schveighoffer (7/24) Dec 09 2010 Multi-threadded code must do it's own handling of shared reads/writes to...
- CrypticMetaphor (7/125) Dec 09 2010 Alright then!
- Jesse Phillips (2/16) Dec 09 2010 It is a linker bug, so Oplink is at fault. What is the bug number you su...
- CrypticMetaphor (3/5) Dec 09 2010 bug number: 5337
- Adam Ruppe (3/3) Dec 09 2010 I almost forgot I wrote that dtips page! Thanks for bringing it up.
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?
Dec 09 2010
On Thu, 09 Dec 2010 09:37:03 -0500, CrypticMetaphor <CrypticMetaphor88 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 steve-laptop:~/testd$ gcc -c testc.c steves 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
Dec 09 2010
On 12/9/2010 3:57 PM, Steven Schveighoffer wrote:On Thu, 09 Dec 2010 09:37:03 -0500, CrypticMetaphor <CrypticMetaphor88 gmail.com> wrote: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 :-( But anyway, it should not compile right? Should I submit a bug report or something? And how I supposed to call the c function?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 steve-laptop:~/testd$ gcc -c testc.c steves 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
Dec 09 2010
On Thu, 09 Dec 2010 10:15:59 -0500, CrypticMetaphor <CrypticMetaphor88 gmail.com> wrote:On 12/9/2010 3:57 PM, Steven Schveighoffer wrote: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?On Thu, 09 Dec 2010 09:37:03 -0500, CrypticMetaphor <CrypticMetaphor88 gmail.com> wrote: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 :-(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 steve-laptop:~/testd$ gcc -c testc.c steves 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? -SteveBut 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.cgiAnd 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
Dec 09 2010
I know I prefer using shared() when interfacing with C. I've tried using __gshared once when interfacing with C code. But I had crashes all the time, using shared instead made my app stable again. It might be related to the way the C code worked, since multiple threads were involved. Anyway.. that's my experience with gshared.. On 12/9/10, Steven Schveighoffer <schveiguy yahoo.com> wrote:On Thu, 09 Dec 2010 10:15:59 -0500, CrypticMetaphor <CrypticMetaphor88 gmail.com> wrote:On 12/9/2010 3:57 PM, Steven Schveighoffer wrote: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?On Thu, 09 Dec 2010 09:37:03 -0500, CrypticMetaphor <CrypticMetaphor88 gmail.com> wrote: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 :-(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 steve-laptop:~/testd$ gcc -c testc.c steves 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? -SteveBut 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.cgiAnd 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
Dec 09 2010
On Thu, 09 Dec 2010 11:38:00 -0500, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:I know I prefer using shared() when interfacing with C. I've tried using __gshared once when interfacing with C code. But I had crashes all the time, using shared instead made my app stable again. It might be related to the way the C code worked, since multiple threads were involved. Anyway.. that's my experience with gshared..__gshared is the equivalent of what normal globals used to be (in D1 and earlier versions of D2). It's the same as a global variable in C. shared is exactly the same as __gshared except the compiler inserts memory barriers around reads/writes (the C compiler does not), and shared is a type modifier, so it's available in the TypeInfo of the variable. Some parts of the runtime use that to determine certain behaviors, and I am aware of one problem with __gshared that needs to be documented -- array appending. __gshared is unprotected sharing, and the type system is not aware that it is shared. Can you remember what specifically you were doing with the variable? BTW, __gshared should have no problems in a single-threadded app. -SteveOn 12/9/10, Steven Schveighoffer <schveiguy yahoo.com> wrote:On Thu, 09 Dec 2010 10:15:59 -0500, CrypticMetaphor <CrypticMetaphor88 gmail.com> wrote: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; }
Dec 09 2010
On 12/9/10, Steven Schveighoffer <schveiguy yahoo.com> wrote:__gshared is unprotected sharing, and the type system is not aware that it is shared. Can you remember what specifically you were doing with the variable?My dev PC is in repairs right now so I don't have the code atm. It's a project that works with audio devices and does some basic processing on audio data. But from what I can recall I would pass my D callback function to C, which would call the callback with an interrupt or very-high level priority thread (it depends on the device driver implementation) at many intervals per second. The D callback would do some processing, update one structure variable (e.g. struct "status"), and return. Inside main() I had an infinite loop which would wait for the device driver to stop calling the callback. One way of knowing if the device driver stopped is to check a flag inside the struct, e.g. a boolean status.done. The problem I was having at first was that the status struct inside the callback was a new TLS variable, and the one main() was seeing was a distinct variable. So main() would never see the updated struct. I've tried marking the struct with __gshared, but this would immediately crash my application. Using shared() instead fixed this problem. This was using DMD 2.048 and I haven't tried newer versions yet. Of course, there are much better ways of notifying when the device driver is done instead of polling the status.done flag all the time. For example, with PortAudio (an audio library) I can use message passing to notify my foreground thread that the background (working) thread is done, or that the device driver has suddenly stopped working. I could do the same with my first project, but PortAudio is a mature and stable library so I've decided not to deal with device drivers directly in my D code (otherwise I would have to write code for all the audio device driver standards -- ASIO, WDM, CoreAudio, etc etc..).
Dec 09 2010
On Thu, 09 Dec 2010 12:24:05 -0500, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:On 12/9/10, Steven Schveighoffer <schveiguy yahoo.com> wrote:Multi-threadded code must do it's own handling of shared reads/writes to __gshared data, such as protecting it with a mutex. Even with shared, it does not guarantee multiple operations are atomic (for example reading two members of a shared struct). -Steve__gshared is unprotected sharing, and the type system is not aware that it is shared. Can you remember what specifically you were doing with the variable?My dev PC is in repairs right now so I don't have the code atm. It's a project that works with audio devices and does some basic processing on audio data. But from what I can recall I would pass my D callback function to C, which would call the callback with an interrupt or very-high level priority thread (it depends on the device driver implementation) at many intervals per second. The D callback would do some processing, update one structure variable (e.g. struct "status"), and return. Inside main() I had an infinite loop which would wait for the device driver to stop calling the callback. One way of knowing if the device driver stopped is to check a flag inside the struct, e.g. a boolean status.done.
Dec 09 2010
On 12/9/2010 5:28 PM, Steven Schveighoffer wrote:On Thu, 09 Dec 2010 10:15:59 -0500, CrypticMetaphor <CrypticMetaphor88 gmail.com> wrote:Alright then! I submitted a my first bug report and added __gshared in front of globalFromD and the output was: 100 500 So it worked. thanks!On 12/9/2010 3:57 PM, Steven Schveighoffer wrote: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?On Thu, 09 Dec 2010 09:37:03 -0500, CrypticMetaphor <CrypticMetaphor88 gmail.com> wrote: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 :-(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 steve-laptop:~/testd$ gcc -c testc.c steves 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? -SteveBut 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.cgiAnd 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
Dec 09 2010
CrypticMetaphor Wrote:On 12/9/2010 5:28 PM, Steven Schveighoffer wrote:It is a linker bug, so Oplink is at fault. What is the bug number you submitted?Yes please, and be sure to specify that it correctly does not compile on linux. http://d.puremagic.com/issues/enter_bug.cgi-SteveAlright then! I submitted a my first bug report and added __gshared in front of globalFromD and the output was: 100 500 So it worked. thanks!
Dec 09 2010
On 12/9/2010 10:04 PM, Jesse Phillips wrote:CrypticMetaphor Wrote: It is a linker bug, so Oplink is at fault. What is the bug number you submitted?bug number: 5337 http://d.puremagic.com/issues/show_bug.cgi?id=5337
Dec 09 2010
I almost forgot I wrote that dtips page! Thanks for bringing it up. I just updated it to include a brief note on __gshared. The rest of it should still work, though. Calling C functions is pretty easy.
Dec 09 2010