Thread overview
Allocating delegate on heap?
Feb 19, 2007
Rick Mann
Feb 19, 2007
Kirk McDonald
Feb 19, 2007
Frits van Bommel
Feb 19, 2007
Kirk McDonald
Feb 19, 2007
Frits van Bommel
February 19, 2007
It appears that a delegate can't be directly allocated on the heap; only as part of a struct, class or array. This is rather annoying.

I'm trying to wrap a C api for event handling (on Mac OS X). In it, you register event handlers as C-linkage callback functions, and you register a bit of "user data" (4 bytes, usually a pointer to something). In your callback, the user data used when you registered is provided, and you typically cast it to your struct or class or whatever.

I'd like to use a delegate as my user data, but it's 8 bytes. So I need to pass a pointer to the delegate, and I need the delegate to live longer than the scope of the code that registered the callback in the first place. However, I don't see how to create a delegate on the heap. Is there any way? (Other than to wrap it in some clunky struct?)

TIA,
Rick
February 19, 2007
Rick Mann wrote:
> It appears that a delegate can't be directly allocated on the heap; only as part of a struct, class or array. This is rather annoying.
> 
> I'm trying to wrap a C api for event handling (on Mac OS X). In it, you register event handlers as C-linkage callback functions, and you register a bit of "user data" (4 bytes, usually a pointer to something). In your callback, the user data used when you registered is provided, and you typically cast it to your struct or class or whatever.
> 
> I'd like to use a delegate as my user data, but it's 8 bytes. So I need to pass a pointer to the delegate, and I need the delegate to live longer than the scope of the code that registered the callback in the first place. However, I don't see how to create a delegate on the heap. Is there any way? (Other than to wrap it in some clunky struct?)
> 
> TIA,
> Rick

[test.d]
import std.stdio;

void main() {
    auto dg = new void delegate();
}

$ dmd test.d
test.d(4): Error: new can only create structs, dynamic arrays or class objects, not void delegate()'s

No, you can't place delegates on the heap. I'm afraid you're stuck with using a struct.

However, there's a very important detail which you should not overlook: You are passing a pointer to GC-controlled data to a C library. The D garbage collector doesn't scan the C library for references, so you will need to keep a reference to any structs you pass to Carbon in your D code. Otherwise, the GC will feel free to collect them when you least expect it. This can be done with an AA:

struct DelegateStruct {
    void delegate() dg;
}

bool[DelegateStruct*] references;

DelegateStruct* get_ref(void delegate() dg) {
    auto s = new DelegateStruct;
    references[s] = true;
    s.dg = dg;
    return s;
}

void drop_ref(DelegateStruct* s) {
    references.remove(s);
}

-- 
Kirk McDonald
http://kirkmcdonald.blogspot.com
Pyd: Connecting D and Python
http://pyd.dsource.org
February 19, 2007
Kirk McDonald wrote:
> [test.d]
> import std.stdio;
> 
> void main() {
>     auto dg = new void delegate();
> }
> 
> $ dmd test.d
> test.d(4): Error: new can only create structs, dynamic arrays or class objects, not void delegate()'s

That error message is wrong, by the way. It may not work for delegates, but it works just fine for ints.

Does anyone know the particular reason delegates are disallowed here?
Since I knew it worked for things like ints, I assumed it worked for all types. I hadn't actually ever tried it though, so I was a bit surprised by this thread...
February 19, 2007
Frits van Bommel wrote:
> Kirk McDonald wrote:
>> [test.d]
>> import std.stdio;
>>
>> void main() {
>>     auto dg = new void delegate();
>> }
>>
>> $ dmd test.d
>> test.d(4): Error: new can only create structs, dynamic arrays or class objects, not void delegate()'s
> 
> That error message is wrong, by the way. It may not work for delegates, but it works just fine for ints.
> 
> Does anyone know the particular reason delegates are disallowed here?
> Since I knew it worked for things like ints, I assumed it worked for all types. I hadn't actually ever tried it though, so I was a bit surprised by this thread...

In my opinion, it /should/ work, but I just go by what the compiler tells me. :-)

Even if this did work, the point about keeping local references to GC-controlled data remains.

-- 
Kirk McDonald
http://kirkmcdonald.blogspot.com
Pyd: Connecting D and Python
http://pyd.dsource.org
February 19, 2007
Kirk McDonald wrote:
> Frits van Bommel wrote:
>> Kirk McDonald wrote:
>>> [test.d]
>>> import std.stdio;
>>>
>>> void main() {
>>>     auto dg = new void delegate();
>>> }
>>>
>>> $ dmd test.d
>>> test.d(4): Error: new can only create structs, dynamic arrays or class objects, not void delegate()'s
>>
>> That error message is wrong, by the way. It may not work for delegates, but it works just fine for ints.
>>
>> Does anyone know the particular reason delegates are disallowed here?
>> Since I knew it worked for things like ints, I assumed it worked for all types. I hadn't actually ever tried it though, so I was a bit surprised by this thread...
> 
> In my opinion, it /should/ work, but I just go by what the compiler tells me. :-)

I agree, that's why I asked if there was any particular reason it didn't :). It seems like a very silly restriction to me.

> Even if this did work, the point about keeping local references to GC-controlled data remains.

I didn't comment on that, did I?
February 19, 2007
"Frits van Bommel" <fvbommel@REMwOVExCAPSs.nl> wrote in message news:erc6ut$2pbv$1@digitalmars.com...
>> Even if this did work, the point about keeping local references to GC-controlled data remains.
>
> I didn't comment on that, did I?

You shouldn't take things so personally, Frits!  Kirk was just saying that as a "back on topic" comment.