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.
 # }

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
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.
 # }

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
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.
 # }

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