Typecasting delegates

Seiji Emery via Digitalmars-d digitalmars-d at puremagic.com
Fri Jun 2 14:14:29 PDT 2017


Hi, bit of a long-time lurker here.

I had a few questions about D delegates: first, D delegates are 
the size of two pointers (16 bytes) on my machine, so I'd assume 
that they're implemented as a pair of pointers; presumably a C 
function pointer, and a GC-managed payload / context / this 
pointer – is this correct?

Secondly, is it safe to typecast delegates for storage purposes – 
ie. cast `void delegate (ref Foo)` to `void delegate()`, or 
something similar? Since delegates seem to just be a pair of 
pointers, it seems like this should work; it's perfectly safe to 
cast C function pointers, for instance, provided that they're 
cast back to the correct type before actually being called. The 
main worry that I have is that this could somehow wreak havoc 
with the GC-managed payload pointer, but I'm not sure. It seems 
like this shouldn't be a problem since payloads change between 
delegates anyways (reference to object vs reference to function 
scope), and delegates with different signatures could point to 
the same object / scope – ie. the payload type and pointed-to 
function signature have nothing to do with each other, and GC 
references to and within the payload should still work properly 
even if I cast a delegate with N arguments to one with zero. But 
I'm just guessing here.


For context, I'm working on an event system for a small hobby 
project, and it would be extremely useful if I could store 
delegates with different type signatures in the same storage 
container; these delegates will always be converted back to the 
correct type signature before being called (probably by storing 
typeinfo of the first / only event argument and comparing that), 
so that's a non-issue. Using a different approach than putting 
listeners that can listen to any kind of event everywhere might 
be better and more efficient architecturally, but would be much 
less flexible / powerful I think. And yes, I've looked into 
std.variadic; I just want something slightly lower-level with 
more control over how I actually dispatch and filter events.


Ah, and uh... one last thing. What's the worst that could happen 
from calling a `ref Foo` signature through a void* pointer? Once 
again, using delegate / function pointer casting shenanigans. Foo 
is a struct. The memory layout seems to be the same, so this 
technically works.

Thanks!



More information about the Digitalmars-d mailing list