Thread overview
implicitly convert function pointers to delegates
Oct 26, 2008
Moritz Warning
Oct 26, 2008
KennyTM~
Oct 26, 2008
KennyTM~
Oct 26, 2008
Frits van Bommel
Oct 26, 2008
Walter Bright
A solution
Oct 27, 2008
downs
Oct 27, 2008
downs
Oct 27, 2008
ore-sama
October 26, 2008
Hi,

some people discovered that functions can be wrapped into delegates without allocation.

Here is one out of several similar solutions:

R delegate(T) toDg(R, T...)(R function(T) fp) {
    struct dg {
        R opCall(T t) {
            return (cast(R function(T)) this) (t);
        }
    }
    R delegate(T) t;
    t.ptr = fp;
    t.funcptr = &dg.opCall;
    return t;
}

I would like to ask if we can get this into the language?
It would make working with delegates and function pointers much more
easier when function pointers implicitly convert to delegates when they
"have to".
October 26, 2008
Moritz Warning wrote:
> Hi,
> 
> some people discovered that functions can be wrapped into delegates without allocation.
> 
> Here is one out of several similar solutions:
> 
> R delegate(T) toDg(R, T...)(R function(T) fp) {
>     struct dg {
>         R opCall(T t) {
>             return (cast(R function(T)) this) (t);
>         }
>     }
>     R delegate(T) t;
>     t.ptr = fp;
>     t.funcptr = &dg.opCall;
>     return t;
> }
> 
> I would like to ask if we can get this into the language?
> It would make working with delegates and function pointers much more easier when function pointers implicitly convert to delegates when they "have to".

vote++ for implicit conversion. An FP can be *safely* converted to any DGs.

BTW,

  alias float delegate (in float) DG;

  float area (in float radius) {
	float r2 = radius * radius;
	return 3.1415926535 * radius;
  }

  DG x;
  x.ptr = null;
  x.funcptr = &area;
  // writefln(typeof(x.funcptr).stringof); // ensure it's an FP not DG.
  writefln(x(10)); // writes 314.159 without any error.


Why this simpler solution is not used? The function pointer can't touch the frame pointer anyway (an FP cannot access stuff outside its scope).
October 26, 2008
On Sun, Oct 26, 2008 at 2:11 PM, KennyTM~ <kennytm@gmail.com> wrote:
> Moritz Warning wrote:
>>
>> Hi,
>>
>> some people discovered that functions can be wrapped into delegates without allocation.
>>
>> Here is one out of several similar solutions:
>>
>> R delegate(T) toDg(R, T...)(R function(T) fp) {
>>    struct dg {
>>        R opCall(T t) {
>>            return (cast(R function(T)) this) (t);
>>        }
>>    }
>>    R delegate(T) t;
>>    t.ptr = fp;
>>    t.funcptr = &dg.opCall;
>>    return t;
>> }
>>
>> I would like to ask if we can get this into the language?
>> It would make working with delegates and function pointers much more
>> easier when function pointers implicitly convert to delegates when they
>> "have to".
>
> vote++ for implicit conversion. An FP can be *safely* converted to any DGs.
>
> BTW,
>
>  alias float delegate (in float) DG;
>
>  float area (in float radius) {
>        float r2 = radius * radius;
>        return 3.1415926535 * radius;
>  }
>
>  DG x;
>  x.ptr = null;
>  x.funcptr = &area;
>  // writefln(typeof(x.funcptr).stringof); // ensure it's an FP not DG.
>  writefln(x(10)); // writes 314.159 without any error.
>
>
> Why this simpler solution is not used? The function pointer can't touch the frame pointer anyway (an FP cannot access stuff outside its scope).
>

The calling conventions for functions and delegates is different. This method does not work in the general case.
October 26, 2008
Jarrett Billingsley wrote:
> On Sun, Oct 26, 2008 at 2:11 PM, KennyTM~ <kennytm@gmail.com> wrote:
>> Moritz Warning wrote:
>>> Hi,
>>>
>>> some people discovered that functions can be wrapped into delegates
>>> without allocation.
>>>
>>> Here is one out of several similar solutions:
>>>
>>> R delegate(T) toDg(R, T...)(R function(T) fp) {
>>>    struct dg {
>>>        R opCall(T t) {
>>>            return (cast(R function(T)) this) (t);
>>>        }
>>>    }
>>>    R delegate(T) t;
>>>    t.ptr = fp;
>>>    t.funcptr = &dg.opCall;
>>>    return t;
>>> }
>>>
>>> I would like to ask if we can get this into the language?
>>> It would make working with delegates and function pointers much more
>>> easier when function pointers implicitly convert to delegates when they
>>> "have to".
>> vote++ for implicit conversion. An FP can be *safely* converted to any DGs.
>>
>> BTW,
>>
>>  alias float delegate (in float) DG;
>>
>>  float area (in float radius) {
>>        float r2 = radius * radius;
>>        return 3.1415926535 * radius;
>>  }
>>
>>  DG x;
>>  x.ptr = null;
>>  x.funcptr = &area;
>>  // writefln(typeof(x.funcptr).stringof); // ensure it's an FP not DG.
>>  writefln(x(10)); // writes 314.159 without any error.
>>
>>
>> Why this simpler solution is not used? The function pointer can't touch the
>> frame pointer anyway (an FP cannot access stuff outside its scope).
>>
> 
> The calling conventions for functions and delegates is different.
> This method does not work in the general case.

I see. And indeed it does not work if I change float to int -- the arguments are shifted by 4 bytes to the left. (How come float works??)
October 26, 2008
KennyTM~ wrote:
> Jarrett Billingsley wrote:
>> On Sun, Oct 26, 2008 at 2:11 PM, KennyTM~ <kennytm@gmail.com> wrote:
>>> BTW,
>>>
>>>  alias float delegate (in float) DG;
>>>
>>>  float area (in float radius) {
>>>        float r2 = radius * radius;
>>>        return 3.1415926535 * radius;
>>>  }
>>>
>>>  DG x;
>>>  x.ptr = null;
>>>  x.funcptr = &area;
>>>  // writefln(typeof(x.funcptr).stringof); // ensure it's an FP not DG.
>>>  writefln(x(10)); // writes 314.159 without any error.
>>>
>>>
>>> Why this simpler solution is not used? The function pointer can't touch the
>>> frame pointer anyway (an FP cannot access stuff outside its scope).
>>>
>>
>> The calling conventions for functions and delegates is different.
>> This method does not work in the general case.
> 
> I see. And indeed it does not work if I change float to int -- the arguments are shifted by 4 bytes to the left. (How come float works??)

Floats are passed differently.

For instance, DMD will put the first argument into EAX if it's an int or pointer (including x.ptr in your code), while it passes floats on the stack.
My x86-64 GDC passes a float in a floating-point register, while ints and pointers go into general-purpose registers (until it runs out of appropriate registers for that function call, anyway).

So on both compilers floats will "work" because they're not moved elsewhere by an extra pointer at the front of the parameter list (which is essentially what happens when you call a function through a delegate's function pointer) while passing in an extra null means the first int an unsuspecting function reads is 0.
October 26, 2008
KennyTM~ wrote:
> (How come float works??)

Because floats are not passed in EAX, they are passed on the stack.
October 27, 2008
When asked to convert a function pointer to a delegate, the compiler could create a small stub that converts from delegate calling convention to FP calling convention, then put that stub in .funcptr and the FP in .ptr.
October 27, 2008
On Sun, Oct 26, 2008 at 11:39 PM, downs <default_357-line@yahoo.de> wrote:
> When asked to convert a function pointer to a delegate, the compiler could create a small stub that converts from delegate calling convention to FP calling convention, then put that stub in .funcptr and the FP in .ptr.
>

Which is precisely what I suggested here: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=78727
October 27, 2008
downs Wrote:

> When asked to convert a function pointer to a delegate, the compiler could create a small stub that converts from delegate calling convention to FP calling convention, then put that stub in .funcptr and the FP in .ptr.

Interestingly, on x86-32 this stub can be generated only once and placed before function prologue (and exported):

Delegate stub:
    pop eax
Function prologue:
    push ebp
    mov ebp, esp

if last parameter is not stored in eax, their calling conventions are compatible and stub is empty :)
October 27, 2008
Jarrett Billingsley wrote:
> On Sun, Oct 26, 2008 at 11:39 PM, downs <default_357-line@yahoo.de> wrote:
>> When asked to convert a function pointer to a delegate, the compiler could create a small stub that converts from delegate calling convention to FP calling convention, then put that stub in .funcptr and the FP in .ptr.
>>
> 
> Which is precisely what I suggested here: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=78727

Sorry :) I wasn't aware of that.