www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Combining D and C

reply Matt <webwraith fastmail.fm> writes:
OK, I'm reallly confused about this. If I have a C source file, and a D module,
what are the things I'd need to create an executable from the two?

How would I go about reading functions and varables from D in C, and vice
versa. I apologise if it is really simple, but I just can't find anything
concrete on exactly what to do. I keep being told to use htod, but what am I
supposed to do once I have used it?
May 16 2009
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Sat, May 16, 2009 at 03:21:28PM -0400, Matt wrote:
 OK, I'm reallly confused about this. If I have a C source file, and a D
module, what are the things I'd need to create an executable from the two?
 
If your main() is in the D file, it is really easy: ====== file.c ========== extern int globalFromD; void functionFromC(int a) { globalFromD = a; } ======= code.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; } ===================== To compile them (assuming linux): gcc -c file.c dmd code.d file.o In general: compile your C file separately, then add the object file from that on to the end of the dmd command line. Run the program: ./code 100 500 --------- Some of the types in the prototypes listed in the D file might change a bit. This is where htod comes in to help. Or you could do the hackish thing I often do and just list void* for all pointers. The fun comes in with accessing C structs. For them, you need to copy/paste and fix the syntax of the struct definition into the extern(C) block. But if your C functions just take pointers to structs, you can typedef void* StructName; in the D and still pass it around. You can't access the members directly, but I find this is often good enough. Anyway, this extern(C) block of the prototypes is what htod automates, so you might not need to worry about this, just import file; // where file is the .d file the htod spits out and start calling your functions. Remember to stick the object file from compiling the .c on the dmd command line though or you'll get linker errors. ====== If your main() is in the C file, things get messier, since you need to set up exceptions and the runtime and whatnot. I don't know the process for that off the top of my head.
 How would I go about reading functions and varables from D in C, and vice
versa. I apologise if it is really simple, but I just can't find anything
concrete on exactly what to do. 
If you need another example, be a bit more specific with what you're trying to do (copy/paste the prototypes here if you can) and I'll try to help. -- Adam D. Ruppe http://arsdnet.net
May 16 2009
parent reply Matt <webwraith fastmail.fm> writes:
Excellent! Thanks, that really helps. I tend to repeat myself when I ask for
help, usually asking in two different ways, as often I'm not too clear the
first time round, hence the second question.

One other quick question, though;
htod works on header files. When compiling the C object file, I take it I
#include the header, then in D, import the htod-generated module?
May 16 2009
parent Jason House <jason.james.house gmail.com> writes:
Matt Wrote:

 Excellent! Thanks, that really helps. I tend to repeat myself when I ask for
help, usually asking in two different ways, as often I'm not too clear the
first time round, hence the second question.
 
 One other quick question, though;
 htod works on header files. When compiling the C object file, I take it I
#include the header, then in D, import the htod-generated module?
That's right
May 16 2009