View mode: basic / threaded / horizontal-split · Log in · Help
October 26, 2008
implicitly convert function pointers to delegates
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
Re: implicitly convert function pointers to delegates
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
Re: implicitly convert function pointers to delegates
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
Re: implicitly convert function pointers to delegates
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
Re: implicitly convert function pointers to delegates
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
Re: implicitly convert function pointers to delegates
KennyTM~ wrote:
> (How come float works??)

Because floats are not passed in EAX, they are passed on the stack.
October 27, 2008
A solution
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
Re: A solution
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
Re: A solution
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
Re: A solution
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.
Top | Discussion index | About this forum | D home