digitalmars.D.learn - Calling D functions from C
- Pontus Pihlgren <pontus update.uu.se> May 27 2008
- Robert Fraser <fraserofthenight gmail.com> May 27 2008
- Matthias Walter <Matthias.Walter st.ovgu.de> May 27 2008
- Pontus Pihlgren <pontus update.uu.se> May 27 2008
- BCS <ao pathlink.com> May 27 2008
- downs <default_357-line yahoo.de> May 27 2008
- BCS <ao pathlink.com> May 27 2008
- downs <default_357-line yahoo.de> May 28 2008
- BCS <ao pathlink.com> May 28 2008
Hi all. Its a rather hypothetical I guess, but is it possible to call D functions from C? If so, are there limitations? Kind Regards, Pontus.
May 27 2008
Pontus Pihlgren wrote:Hi all. Its a rather hypothetical I guess, but is it possible to call D functions from C? If so, are there limitations? Kind Regards, Pontus.
extern(C) your D functions & enjoy! If you're not running the D garbage collector, don't rely on garbage collection happening (obvious), and a bit less obvious is that many libraries require their static constructors to be called, so be sure to run those first. Also, don't throw exceptions over D-C lines. There's probably other limitations I'm not thinking of/don't know of.
May 27 2008
Pontus Pihlgren Wrote:Hi all. Its a rather hypothetical I guess, but is it possible to call D functions from C? If so, are there limitations? Kind Regards, Pontus.
If you want to really call the D function from C code, compiling with a C compiler, this can get tricky, as the C compiler normally does not know the ABI of D. It therefore does not know in which registers / stack slots to put which argument, etc. But you can write a Wrapper routine in D which simply calls your D routine but has an extern (C) calling convention: # extern (C) int myFunctionWrapper (char a, int b, char* c) # { # return myFunction (a,b,c); // myFunction is a normal D function. # } With this code you can call myFunctionWrapper from your C code like you do normally. Alternatively you can code all your C stuff in a .d file, putting extern (C) around everything. Then you can call it without a wrapper, too. best regards Matthias Walter
May 27 2008
Matthias Walter skrev:Pontus Pihlgren Wrote:Hi all. Its a rather hypothetical I guess, but is it possible to call D functions from C? If so, are there limitations? Kind Regards, Pontus.
If you want to really call the D function from C code, compiling with a C compiler, this can get tricky, as the C compiler normally does not know the ABI of D. It therefore does not know in which registers / stack slots to put which argument, etc. But you can write a Wrapper routine in D which simply calls your D routine but has an extern (C) calling convention: # extern (C) int myFunctionWrapper (char a, int b, char* c) # { # return myFunction (a,b,c); // myFunction is a normal D function. # } With this code you can call myFunctionWrapper from your C code like you do normally. Alternatively you can code all your C stuff in a .d file, putting extern (C) around everything. Then you can call it without a wrapper, too. best regards Matthias Walter
That sound almost to easy, I thought that extern could only refer to, you know, external functions and not to declare new functions. Looking more closely at the documentation at http://www.digitalmars.com/d/2.0/interfaceToC.html verifies it :) I guess I must have missed it the first time I read it. Thanks, Pontus.
May 27 2008
Reply to Matthias,# extern (C) int myFunctionWrapper (char a, int b, char* c) # { # return myFunction (a,b,c); // myFunction is a normal D function. # }
that deserves a template. I guess I known what to do at lunch today.
May 27 2008
BCS wrote:Reply to Matthias,# extern (C) int myFunctionWrapper (char a, int b, char* c) # { # return myFunction (a,b,c); // myFunction is a normal D function. # }
that deserves a template. I guess I known what to do at lunch today.
template Forward(string NAME) { mixin("extern(C) ReturnType!(&"~NAME~") c_"~NAME~"(ParameterTypeTuple!(&"~NAME~") p) { return "~NAME~"(p); }"); } Untested, but should work. --downs
May 27 2008
Reply to Downs,BCS wrote:Reply to Matthias,# extern (C) int myFunctionWrapper (char a, int b, char* c) # { # return myFunction (a,b,c); // myFunction is a normal D function. # }
I guess I known what to do at lunch today.
mixin("extern(C) ReturnType!(&"~NAME~") c_"~NAME~"(ParameterTypeTuple!(&"~NAME~") p) { return "~NAME~"(p); }"); } Untested, but should work. --downs
maybe, I'd kind rather not use a mixin for that. (I avoid them wherever I can) I'll take real a pass at it later. On second look it seem the mixin is needed to make the name work but it seem to be over kill for the rest // untested template Forward(alias NAME) { mixin( "extern(C) ReturnType!(&NAME) c_"~NAME.stringof~"(ParameterTypeTuple!(&NAME) p) { return NAME(p);}" ); }
May 27 2008
BCS wrote:Reply to Downs,BCS wrote:Reply to Matthias,# extern (C) int myFunctionWrapper (char a, int b, char* c) # { # return myFunction (a,b,c); // myFunction is a normal D function. # }
I guess I known what to do at lunch today.
mixin("extern(C) ReturnType!(&"~NAME~") c_"~NAME~"(ParameterTypeTuple!(&"~NAME~") p) { return "~NAME~"(p); }"); } Untested, but should work. --downs
maybe, I'd kind rather not use a mixin for that. (I avoid them wherever I can) I'll take real a pass at it later. On second look it seem the mixin is needed to make the name work but it seem to be over kill for the rest // untested template Forward(alias NAME) { mixin( "extern(C) ReturnType!(&NAME) c_"~NAME.stringof~"(ParameterTypeTuple!(&NAME) p) { return NAME(p);}" ); }
For example, the above code would fail if it for some obscure reason contains spaces (or other invalid characters). If you let the user pass a string, at least you know where the blame lies. --downs
May 28 2008
Reply to Downs,BCS wrote:Reply to Downs,BCS wrote:Reply to Matthias,# extern (C) int myFunctionWrapper (char a, int b, char* c) # { # return myFunction (a,b,c); // myFunction is a normal D function. # }
I guess I known what to do at lunch today.
mixin("extern(C) ReturnType!(&"~NAME~") c_"~NAME~"(ParameterTypeTuple!(&"~NAME~") p) { return "~NAME~"(p); }"); } Untested, but should work. --downs
wherever I can) I'll take real a pass at it later. On second look it seem the mixin is needed to make the name work but it seem to be over kill for the rest // untested template Forward(alias NAME) { mixin( "extern(C) ReturnType!(&NAME) c_"~NAME.stringof~"(ParameterTypeTuple!(&NAME) p) { return NAME(p);}" ); }
For example, the above code would fail if it for some obscure reason contains spaces (or other invalid characters). If you let the user pass a string, at least you know where the blame lies. --downs
// untested template Forward(alias fn, char[] name) { mixin( "extern(C)ReturnType!(&NAME)"~name~"(ParameterTypeTuple!(&fn) p){return fn(p);}" ); }
May 28 2008









Robert Fraser <fraserofthenight gmail.com> 