Just thought I'd post this before it's too late (some will argue it already is too late, but I don't think so):
Please make the calling convention for delegates compatible with the one for functions. I want to be able to write my API using only delegates, and allow users to pass also globals (function pointers) for callbacks.
The two workarounds currently are
* wrapping the function in a dummy delegate literal (I don't like having to do this; it's not about the work, but it looks clumsy)
* provide an API using delegates and one using function pointers (much like std.thread.Thread's constructor; needs extra code, for what?)
If I'd be asked to submit ONE issue for "to do before 1.0", this would be it.
L.

Lionello Lunesu wrote:
> Just thought I'd post this before it's too late (some will argue it already is too late, but I don't think so):
> > Please make the calling convention for delegates compatible with the one for functions. I want to be able to write my API using only delegates, and allow users to pass also globals (function pointers) for callbacks.
> > The two workarounds currently are
> > * wrapping the function in a dummy delegate literal (I don't like having to do this; it's not about the work, but it looks clumsy)
> > * provide an API using delegates and one using function pointers (much like std.thread.Thread's constructor; needs extra code, for what?)
> > If I'd be asked to submit ONE issue for "to do before 1.0", this would be it.
> > L.
One major problem: This would make function pointers incompatible with C function pointers, making interfacing with a huge chunk of software impossible.
One solution nobody will like (hell, I don't even like it): Have a special value for the scope part of the delegate that basically implies "this is not really a delegate", and will cause the call to the delegate to not pass it as the first argument. This would incur an if for delegate calls, but would make function pointers castable to delegates.
- Gregor Richards

Gregor Richards wrote:
> Lionello Lunesu wrote:
> >> Just thought I'd post this before it's too late (some will argue it already is too late, but I don't think so):
>>>> Please make the calling convention for delegates compatible with the one for functions. I want to be able to write my API using only delegates, and allow users to pass also globals (function pointers) for callbacks.
>>>> The two workarounds currently are
>>>> * wrapping the function in a dummy delegate literal (I don't like having to do this; it's not about the work, but it looks clumsy)
>>>> * provide an API using delegates and one using function pointers (much like std.thread.Thread's constructor; needs extra code, for what?)
>>>> If I'd be asked to submit ONE issue for "to do before 1.0", this would be it.
>>>> L.
> > > One major problem: This would make function pointers incompatible with C function pointers, making interfacing with a huge chunk of software impossible.
> > One solution nobody will like (hell, I don't even like it): Have a special value for the scope part of the delegate that basically implies "this is not really a delegate", and will cause the call to the delegate to not pass it as the first argument. This would incur an if for delegate calls, but would make function pointers castable to delegates.
> > - Gregor Richards
And a solution that's less nasty: Allow casting of function pointers to delegate pointers by automatic thunktion generation.
- Gregor Richards

"Gregor Richards" <Richards@codu.org> wrote in message news:4548CD75.80803@codu.org...> And a solution that's less nasty: Allow casting of function pointers to delegate pointers by automatic thunktion generation.
I like that a lot better. But if you're wrapping a function pointer in a delegate reference, is a thunk really needed? I mean, the function won't be accessing the context pointer, so why not just set the delegate's context pointer to null?
i.e.
int foo()
{
}
int delegate() bar = cast(int delegate())&foo;
// bar's function address is &foo, and bar.ptr == null

Gregor Richards wrote:
> It's also DMD-with-D-calling-convention-specific X_X
> > (eg: won't work with GDC, won't work with C functions)
It could easily be done, just have the thunks bounce into a function the Thunk template builds that reorder the arguments (this function can gratefully be written in D), and add a post-call patch to fix the stack.
I'm not trying to argue that this is the way it should be, obviously the compiler should be handling this magic. But while I've never heard Walter say anything about thunking, I can predict with great accuracy that he'll be against it because it's a hidden allocation [of great utility]. It seems like it would be better to have SOMETHING to do the task than to keep crashing against the barricade and getting more and more frustrated.
Anyway, thunking D to C would generally be pretty hazardous because as soon as you pass it to the C library it'll be collectable, and since the allocation IS hidden it would be easy to miss. Manually thunking C function pointers isn't difficult with any correctly-written C library and doesn't happen often enough in my experience (once per wrapper, to be exact) to bother with.
What happens more often is the need to cast from function pointers to delegates (or SOME common function pointer), constrained to the D calling convention. Since that can be done without allocations, I think that and only that should be made part of the language. The rest can follow with time, or not.

Burton Radons wrote:
> Gregor Richards wrote:
> >> It's also DMD-with-D-calling-convention-specific X_X
>>>> (eg: won't work with GDC, won't work with C functions)
> > > It could easily be done, just have the thunks bounce into a function the Thunk template builds that reorder the arguments (this function can gratefully be written in D), and add a post-call patch to fix the stack.
> > I'm not trying to argue that this is the way it should be, obviously the compiler should be handling this magic. But while I've never heard Walter say anything about thunking, I can predict with great accuracy that he'll be against it because it's a hidden allocation [of great utility]. It seems like it would be better to have SOMETHING to do the task than to keep crashing against the barricade and getting more and more frustrated.
> > Anyway, thunking D to C would generally be pretty hazardous because as soon as you pass it to the C library it'll be collectable, and since the allocation IS hidden it would be easy to miss. Manually thunking C function pointers isn't difficult with any correctly-written C library and doesn't happen often enough in my experience (once per wrapper, to be exact) to bother with.
> > What happens more often is the need to cast from function pointers to delegates (or SOME common function pointer), constrained to the D calling convention. Since that can be done without allocations, I think that and only that should be made part of the language. The rest can follow with time, or not.
If I recall properly, DMC uses thunktions for C++'s lame pseudodelegates :)
- Gregor Richards

Gregor Richards wrote:
> Jarrett Billingsley wrote:
>> "Gregor Richards" <Richards@codu.org> wrote in message news:4548CD75.80803@codu.org...>>>>>>> And a solution that's less nasty: Allow casting of function pointers to delegate pointers by automatic thunktion generation.
>>>>>> I like that a lot better. But if you're wrapping a function pointer in a delegate reference, is a thunk really needed? I mean, the function won't be accessing the context pointer, so why not just set the delegate's context pointer to null?
>>>> i.e.
>>>> int foo()
>> {
>>>> }
>>>> int delegate() bar = cast(int delegate())&foo;
>> // bar's function address is &foo, and bar.ptr == null
>>> > The context pointer isn't magic, it's passed as an argument to the function. So if you directly casted, you'd end up with an extra argument passed to the function, any argument processing would be off-by-one.
> > - Gregor Richards
Actually, it's passed in a register, so it could be made to work.
L.