Jump to page: 1 2
Thread overview
Convert a delegate to a function (i.e. make a thunk)
Apr 25, 2012
Mehrdad
Apr 25, 2012
Jonathan M Davis
Apr 25, 2012
David Nadlinger
Apr 25, 2012
David Nadlinger
Apr 25, 2012
H. S. Teoh
Apr 25, 2012
David Nadlinger
Apr 25, 2012
H. S. Teoh
Apr 27, 2012
David Brown
Apr 26, 2012
Daniel Murphy
April 25, 2012
It would be nice if there was a way to convert delegates to functions/thunks, because certain annoying tasks (e.g. 'WndProc's in Windows) would become a heck of a lot easier.

Is there any way to already do this? If not, how about adding a toFunction() method in std.functional?

(This would of course require making data executable, so that's why it's painful to get right. ATL uses a pool of some sort, I think... so if toFunction() did this internally, with a separate pool, it would reduce a lot of memory management burden from the programmer.) 

April 25, 2012
On Wednesday, April 25, 2012 14:02:53 Mehrdad wrote:
> It would be nice if there was a way to convert delegates to functions/thunks, because certain annoying tasks (e.g. 'WndProc's in Windows) would become a heck of a lot easier.
> 
> Is there any way to already do this? If not, how about adding a toFunction() method in std.functional?
> 
> (This would of course require making data executable, so that's why it's painful to get right. ATL uses a pool of some sort, I think... so if toFunction() did this internally, with a separate pool, it would reduce a lot of memory management burden from the programmer.)

You could have a function which took a delegate and called it (which could probably be done with void* if the function has to be an extern(C) function), or if the function didn't need to be pure, then you could have a function which called a module-level variable which the delegate had been assigned to. But you can't convert a delegate to a function without passing the delegate to the function one way or another, because the function doesn't have a context (not being a delegate).

- Jonathan M Davis
April 25, 2012
On 25-04-2012 23:27, Jonathan M Davis wrote:
> On Wednesday, April 25, 2012 14:02:53 Mehrdad wrote:
>> It would be nice if there was a way to convert delegates to
>> functions/thunks, because certain annoying tasks (e.g. 'WndProc's in
>> Windows) would become a heck of a lot easier.
>>
>> Is there any way to already do this? If not, how about adding a toFunction()
>> method in std.functional?
>>
>> (This would of course require making data executable, so that's why it's
>> painful to get right. ATL uses a pool of some sort, I think... so if
>> toFunction() did this internally, with a separate pool, it would reduce a
>> lot of memory management burden from the programmer.)
>
> You could have a function which took a delegate and called it (which could
> probably be done with void* if the function has to be an extern(C) function),
> or if the function didn't need to be pure, then you could have a function
> which called a module-level variable which the delegate had been assigned to.
> But you can't convert a delegate to a function without passing the delegate to
> the function one way or another, because the function doesn't have a context
> (not being a delegate).
>
> - Jonathan M Davis

http://en.wikipedia.org/wiki/Thunk_(functional_programming)
http://catb.org/jargon/html/T/thunk.html

You may be able to do something like this with libffi.

(See https://github.com/lycus/libffi-d for a D binding.)

-- 
- Alex
April 25, 2012
On Wednesday, 25 April 2012 at 21:27:30 UTC, Jonathan M Davis wrote:
> But you can't convert a delegate to a function without passing the delegate to
> the function one way or another, because the function doesn't have a context
> (not being a delegate).

That's the whole point of the question - you _can_ pull this off if you create a small code fragment somewhere in memory which calls the delegate with that specific context argument, and then set your function pointer to its address (similar to thunks in most vtable implementations or SEH, if you are familiar with these). Now, the only problem is that executing data is not quite easy, mostly because of security mechanisms (W^X, NX and friends).

As for the original question, I didn't need the feature so far (many C libraries provide a void* bit of data to use at the client's discretion), but if you need inspiration on how to implement it, I'd look at projects like Mono and FFI libraries which likely need to provide similar functionality.

Would probably be a good addition to Phobos.

David
April 25, 2012
On 26-04-2012 00:06, David Nadlinger wrote:
> On Wednesday, 25 April 2012 at 21:27:30 UTC, Jonathan M Davis wrote:
>> But you can't convert a delegate to a function without passing the
>> delegate to
>> the function one way or another, because the function doesn't have a
>> context
>> (not being a delegate).
>
> That's the whole point of the question - you _can_ pull this off if you
> create a small code fragment somewhere in memory which calls the
> delegate with that specific context argument, and then set your function
> pointer to its address (similar to thunks in most vtable implementations
> or SEH, if you are familiar with these). Now, the only problem is that
> executing data is not quite easy, mostly because of security mechanisms
> (W^X, NX and friends).
>
> As for the original question, I didn't need the feature so far (many C
> libraries provide a void* bit of data to use at the client's
> discretion), but if you need inspiration on how to implement it, I'd
> look at projects like Mono and FFI libraries which likely need to
> provide similar functionality.
>
> Would probably be a good addition to Phobos.
>
> David

libffi can do it. There's a reason I wanted std.ffi. ;) (Unfortunately interest in such a module seemed low earlier.)

-- 
- Alex
April 25, 2012
On Wednesday, 25 April 2012 at 22:25:10 UTC, Alex Rønne Petersen wrote:
> libffi can do it. There's a reason I wanted std.ffi. ;) (Unfortunately interest in such a module seemed low earlier.)

Ah, you beat me to it - didn't see your answer while I was at the reply screen. ;)

David


April 25, 2012
On Thu, Apr 26, 2012 at 12:06:54AM +0200, David Nadlinger wrote:
> On Wednesday, 25 April 2012 at 21:27:30 UTC, Jonathan M Davis wrote:
> >But you can't convert a delegate to a function without passing the delegate to the function one way or another, because the function doesn't have a context (not being a delegate).
> 
> That's the whole point of the question - you _can_ pull this off if you create a small code fragment somewhere in memory which calls the delegate with that specific context argument, and then set your function pointer to its address (similar to thunks in most vtable implementations or SEH, if you are familiar with these). Now, the only problem is that executing data is not quite easy, mostly because of security mechanisms (W^X, NX and friends).

This is like GCC's implementation of nested function pointers using trampolines:

	http://gcc.gnu.org/onlinedocs/gccint/Trampolines.html

These nested function pointers have access to their containing lexical scope, even though they are just regular, non-fat pointers.

Something similar can be used here, though for full-fledged D delegates the trampoline would need to be in executable heap memory. I believe nowadays heap memory is non-executable due to security concerns with heap overflow exploits, right? So this may require special treatment.


T

-- 
PNP = Plug 'N' Pray
April 25, 2012
On Wednesday, 25 April 2012 at 22:31:59 UTC, H. S. Teoh wrote:
> I believe
> nowadays heap memory is non-executable due to security concerns with
> heap overflow exploits, right? So this may require special treatment.

Yes; it usually boils down to allocating a dedicated page and then setting the executable flag after you are done with setting up your code (e.g. using VirtualAlloc/VirtualProtect on Windows).

David
April 25, 2012
On Thu, Apr 26, 2012 at 12:47:42AM +0200, David Nadlinger wrote:
> On Wednesday, 25 April 2012 at 22:31:59 UTC, H. S. Teoh wrote:
> >I believe nowadays heap memory is non-executable due to security concerns with heap overflow exploits, right? So this may require special treatment.
> 
> Yes; it usually boils down to allocating a dedicated page and then setting the executable flag after you are done with setting up your code (e.g. using VirtualAlloc/VirtualProtect on Windows).
[...]

Does turning on the executable flag also make it read-only?  If so, we'd need to allocate a page per wrapper function, which seems a bit excessive. Or is it possible to turn it off temporarily, add more code, and turn it back on? (Seems like that should be prohibited, since otherwise it would just be too easy to exploit, and would defeat the purpose of protecting it in the first place.)


T

-- 
Arise, you prisoners of Windows
Arise, you slaves of Redmond, Wash,
The day and hour soon are coming
When all the IT folks say "Gosh!"
It isn't from a clever lawsuit
That Windowsland will finally fall,
But thousands writing open source code
Like mice who nibble through a wall.
-- The Linux-nationale by Greg Baker
April 26, 2012
"Mehrdad" <wfunction@hotmail.com> wrote in message news:jn9ops$13bs$1@digitalmars.com...
> It would be nice if there was a way to convert delegates to functions/thunks, because certain annoying tasks (e.g. 'WndProc's in Windows) would become a heck of a lot easier.
>
> Is there any way to already do this? If not, how about adding a toFunction() method in std.functional?
>

Well, there's this: http://pastebin.com/XwEb2cpm

But it's pre-3797, and probably doesn't work anywhere except win32.


« First   ‹ Prev
1 2