www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - delegates/lambas do not pick up calling convention

reply Johnson Jones <JJ Dynomite.com> writes:
given somethign like Threads.threadsAddIdle

which takes an extern(C) int (void*)

we can't seem to do

threadsAddIdle((void*) { }, null);

nor



because D complains is not the correct type nor can we do


delegate(void*)

or

extern(C) delegate(void*) {}


and have to resort to verbosity to get it to work. Is there a way 
around that? Why can't D realize that an inline lambda should use 
the same calling convention? There is no harm in doing so.

Maybe I'm doing it wrong:

I've tried

											import gdk.Threads;
												alias DD = static extern(C) int delegate(void*);
												auto x = (void*)
												{
													return 1;
												};
												gdk.Threads.threadsAddIdle(x, null);


which gives the error

(extern (C) int function(void* userData) funct, void* data) is 
not callable using argument types
             int function(void* _param_0) pure nothrow  nogc 
 safe, typeof(null))


While one can do something like

										gdk.Threads.threadsAddIdle(cast(GSourceFunc)(void* data)
													   {
																							   return 1;
													   }, null);

which seems to work but the cast seems superfluous as D should be 
able to implicitly figure that out since it's an inline delegate.
Aug 09
next sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 8/9/17 7:52 PM, Johnson Jones wrote:
 given somethign like Threads.threadsAddIdle
 
 which takes an extern(C) int (void*)
 
 we can't seem to do
 
 threadsAddIdle((void*) { }, null);
Because D tries to avoid situations where the type depends on the usage. The implied type is based solely on the expression (in most cases, there are a few cases where it is affected by usage). FYI I also code in swift, and I run into situations all the time where the compiler can't figure out types for a statement because it hits some weird corner case that causes too much recursion in the compiler. In those cases, the compiler says "please split up your statement into multiple lines". So I'm kind of glad D doesn't go this route, as nice as it is conceptually. -Steve
Aug 09
prev sibling next sibling parent ag0aep6g <anonymous example.com> writes:
On 08/10/2017 01:52 AM, Johnson Jones wrote:
 I've tried
 
                                              import gdk.Threads;
                                                  alias DD = static 
 extern(C) int delegate(void*);
                                                  auto x = (void*)
                                                  {
                                                      return 1;
                                                  };
                                                  
 gdk.Threads.threadsAddIdle(x, null);
1) You probably meant to apply `DD` to `x`. 2) `x` must be a `function`, not a `delegate`. 3) (optional) `static` is not needed. So: ---- import gdk.Threads; alias DD = extern(C) int function(void*); DD x = (void*) { return 1; }; gdk.Threads.threadsAddIdle(x, null); ----
Aug 10
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 10.08.2017 01:52, Johnson Jones wrote:
 given somethign like Threads.threadsAddIdle
 
 which takes an extern(C) int (void*)
 
 we can't seem to do
 
 threadsAddIdle((void*) { }, null);
I think this is a compiler bug. Try: threadsAddIdle((x){ }, null); It seems that the calling convention is deduced only if the parameter type needs to be deduced too. https://issues.dlang.org/show_bug.cgi?id=17739
Aug 10
prev sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Wednesday, 9 August 2017 at 23:52:00 UTC, Johnson Jones wrote:
 extern(C) delegate(void*) {}
You should very rarely use extern(C) delegate... delegate is a D type, so the C function is almost certainly not actually receiving it. Only time you'd want an extern(C) using D types like delegates, arrays, strings, etc., is if the receiver is actually also written in D. idk if this would fix your problem, but it should be changed regardless.
Aug 10
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 10.08.2017 15:22, Adam D. Ruppe wrote:
 On Wednesday, 9 August 2017 at 23:52:00 UTC, Johnson Jones wrote:
 extern(C) delegate(void*) {}
You should very rarely use extern(C) delegate... delegate is a D type, so the C function is almost certainly not actually receiving it. Only time you'd want an extern(C) using D types like delegates, arrays, strings, etc., is if the receiver is actually also written in D. idk if this would fix your problem, but it should be changed regardless.
gdk is actually using a function with arguments of type (extern(C) int function(void*),void*). Anyway, I think there are use cases for extern(C) delegates too, along the following lines: alias D=extern(C) int delegate(int); struct F(S,T...){ // this struct is compatible with C void* ptr; extern(C) S function(void*,T) funptr; auto opCall(T args){ return funptr(ptr,args); } } void main(){ int y=2; D dg=(x)=>x+y; auto f=*cast(F!(int,int)*)&dg; import std.stdio; writeln(f(3)); }
Aug 10