www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Calling D from C - What's the present status?

reply hauptmech <th_sx mailsnare.net> writes:
I'd like to maintain an internal (to my company) code library in D
but provide customers with a libxxx.a and *.h files so they can use C.

I'd like to provide access to classes and members. My C library code
is more or less object oriented (ei pass in a pointer to data as the
first arg to a "member" function) so customers can deal with that.

I read the short snippet that said functions attributed as extern(C)
can be called... and I vaguely rememeber experimenting a year ago and
being able to call class members with a little pointer abuse...

Is there a compiler switch that will generate a nice *.h file?!?

Or perhapse more reasonably; does anyone know of any projects out
there geared towards providing C bindings for D libraries in an
automated way?

hauptmech
Jan 19 2007
parent reply Daniel Keep <daniel.keep+lists gmail.com> writes:
hauptmech wrote:
 I'd like to maintain an internal (to my company) code library in D
 but provide customers with a libxxx.a and *.h files so they can use C.
 
 I'd like to provide access to classes and members. My C library code
 is more or less object oriented (ei pass in a pointer to data as the
 first arg to a "member" function) so customers can deal with that.
 
 I read the short snippet that said functions attributed as extern(C)
 can be called... and I vaguely rememeber experimenting a year ago and
 being able to call class members with a little pointer abuse...
 
 Is there a compiler switch that will generate a nice *.h file?!?
 
 Or perhapse more reasonably; does anyone know of any projects out
 there geared towards providing C bindings for D libraries in an
 automated way?
 
 hauptmech

AFAIK, there is no automated mechanism for generating .h files -- historically, we've been more worried about calling back to C and C++ than the other way around :) Here's what I *do* know on the subject: "extern(C)" lets you use perfectly normal C calling conventions. So, for example, if you compile this: extern(C) int add(int a, int b) { return a + b; } to an object file, and link it into a C program that has the following declaration somewhere: int add(int, int); Then it should all work as expected. The trouble comes in because of D's additional features such as the garbage collector (used by default for all heap allocations), module constructors/destructors, etc. As for exposing D classes to C, you would have to do what you would normally do with C++: build a "flat api" wrapper around the classes for C to use. I'm afraid I can't really offer anything more; if you check out the phobos source code (which comes with DMD), it contains the main function used by D programs (which in turn calls the main function defined in your code). This includes details on how to do things like start up the garbage collector and do initialisation, etc. Best of luck to you :) -- Daniel
Jan 20 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Daniel Keep wrote:
 hauptmech wrote:
 I'd like to maintain an internal (to my company) code library in D
 but provide customers with a libxxx.a and *.h files so they can use C.

 I'd like to provide access to classes and members. My C library code
 is more or less object oriented (ei pass in a pointer to data as the
 first arg to a "member" function) so customers can deal with that.

 I read the short snippet that said functions attributed as extern(C)
 can be called... and I vaguely rememeber experimenting a year ago and
 being able to call class members with a little pointer abuse...

 Is there a compiler switch that will generate a nice *.h file?!?

 Or perhapse more reasonably; does anyone know of any projects out
 there geared towards providing C bindings for D libraries in an
 automated way?

 hauptmech

AFAIK, there is no automated mechanism for generating .h files -- historically, we've been more worried about calling back to C and C++ than the other way around :) Here's what I *do* know on the subject: "extern(C)" lets you use perfectly normal C calling conventions. So, for example, if you compile this: extern(C) int add(int a, int b) { return a + b; } to an object file, and link it into a C program that has the following declaration somewhere: int add(int, int); Then it should all work as expected. The trouble comes in because of D's additional features such as the garbage collector (used by default for all heap allocations), module constructors/destructors, etc. As for exposing D classes to C, you would have to do what you would normally do with C++: build a "flat api" wrapper around the classes for C to use. I'm afraid I can't really offer anything more; if you check out the phobos source code (which comes with DMD), it contains the main function used by D programs (which in turn calls the main function defined in your code). This includes details on how to do things like start up the garbage collector and do initialisation, etc. Best of luck to you :) -- Daniel

Seems like there should be a single handy extern (C) function in phobos to handle that standard startup and shutdown stuff. I've seen a couple of D programs that do this manually (I think the most recent was one of Kirk's PyD samples). Is there some reason that stuff can't just be thrown in a single DRuntimeInit / DRuntimeClose pair of functions? Tango folks? --bb
Jan 20 2007
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Bill Baxter wrote:
 Seems like there should be a single handy extern (C) function in phobos 
 to handle that standard startup and shutdown stuff.  I've seen a couple 
 of D programs that do this manually (I think the most recent was one of 
 Kirk's PyD samples).  Is there some reason that stuff can't just be 
 thrown in a single DRuntimeInit / DRuntimeClose pair of functions?

Well, for one thing, the standard wrapper also catches exceptions. That's kind of hard to do with a pair of functions. Other than that, I don't see a problem with it.
 Tango folks?
 --bb

Jan 20 2007
parent Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Frits van Bommel wrote:
 Bill Baxter wrote:
 
 Seems like there should be a single handy extern (C) function in 
 phobos to handle that standard startup and shutdown stuff.  I've seen 
 a couple of D programs that do this manually (I think the most recent 
 was one of Kirk's PyD samples).  Is there some reason that stuff can't 
 just be thrown in a single DRuntimeInit / DRuntimeClose pair of 
 functions?

Well, for one thing, the standard wrapper also catches exceptions. That's kind of hard to do with a pair of functions. Other than that, I don't see a problem with it.

Each function that is directly exposed to C must ensure that exceptions do not escape from your D code. Pyd does this with a handy function template that translates D exceptions into Python exceptions: http://pyd.dsource.org/except_wrapping.html You will probably have to think of some other way to handle exceptions escaping from D, but something like Pyd's exception_catcher is one solution to consider. -- Kirk McDonald Pyd: Wrapping Python with D http://pyd.dsource.org
Jan 20 2007