Thread overview
delegates/lambas do not pick up calling convention
Aug 09, 2017
Johnson Jones
Aug 10, 2017
ag0aep6g
Aug 10, 2017
Timon Gehr
Aug 10, 2017
Adam D. Ruppe
Aug 10, 2017
Timon Gehr
August 09, 2017
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.



August 09, 2017
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
August 10, 2017
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);
----
August 10, 2017
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
August 10, 2017
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.
August 10, 2017
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));
}