www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Calling D functions from C

reply Pontus Pihlgren <pontus update.uu.se> writes:
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
next sibling parent Robert Fraser <fraserofthenight gmail.com> writes:
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
prev sibling parent reply Matthias Walter <Matthias.Walter st.ovgu.de> writes:
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
next sibling parent Pontus Pihlgren <pontus update.uu.se> writes:
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
prev sibling parent reply BCS <ao pathlink.com> writes:
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
parent reply downs <default_357-line yahoo.de> writes:
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
parent reply BCS <ao pathlink.com> writes:
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.
 # }
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
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
parent reply downs <default_357-line yahoo.de> writes:
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.
 # }
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
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);}" ); }
Remember. stringof is not guaranteed to be in any sort of sane format. 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
parent BCS <ao pathlink.com> writes:
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.
 # }
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
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);}" ); }
Remember. stringof is not guaranteed to be in any sort of sane format. 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