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