digitalmars.D.learn - Allocating delegate on heap?
- Rick Mann (5/5) Feb 19 2007 It appears that a delegate can't be directly allocated on the heap; only...
- Kirk McDonald (35/43) Feb 19 2007 [test.d]
- Frits van Bommel (7/17) Feb 19 2007 That error message is wrong, by the way. It may not work for delegates,
- Kirk McDonald (10/29) Feb 19 2007 In my opinion, it /should/ work, but I just go by what the compiler
- Frits van Bommel (4/29) Feb 19 2007 I agree, that's why I asked if there was any particular reason it didn't...
- Jarrett Billingsley (4/7) Feb 19 2007 You shouldn't take things so personally, Frits! Kirk was just saying th...
- Rick Mann (3/9) Feb 19 2007 Yes, thank you, I was aware of that. As it turns out, there's other stuf...
- Bill Baxter (5/17) Feb 19 2007 That's going to tie you to a particular gc implementation, though. So I...
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
Feb 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
Feb 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()'sThat 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...
Feb 19 2007
Frits van Bommel wrote:Kirk McDonald wrote: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[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()'sThat 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...
Feb 19 2007
Kirk McDonald wrote:Frits van Bommel wrote: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.Kirk McDonald wrote:In my opinion, it /should/ work, but I just go by what the compiler tells me. :-)[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()'sThat 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...Even if this did work, the point about keeping local references to GC-controlled data remains.I didn't comment on that, did I?
Feb 19 2007
"Frits van Bommel" <fvbommel REMwOVExCAPSs.nl> wrote in message news:erc6ut$2pbv$1 digitalmars.com...You shouldn't take things so personally, Frits! Kirk was just saying that as a "back on topic" comment.Even if this did work, the point about keeping local references to GC-controlled data remains.I didn't comment on that, did I?
Feb 19 2007
Kirk McDonald Wrote: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:Yes, thank you, I was aware of that. As it turns out, there's other stuff I need to do with my delegate that I can't do (namely, treat the .ptr portion of it as a pointer to a class derived from some interface Foo), so I ended up having to create a little class wrapper. I add the class to the GC's root with std.gc.addRoot(). This should work, right (rather than storing it in an AA)?
Feb 19 2007
Rick Mann wrote:Kirk McDonald Wrote:That's going to tie you to a particular gc implementation, though. So I think the practice should be avoided unless you have a compelling reason to do it that way. --bbHowever, 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:Yes, thank you, I was aware of that. As it turns out, there's other stuff I need to do with my delegate that I can't do (namely, treat the .ptr portion of it as a pointer to a class derived from some interface Foo), so I ended up having to create a little class wrapper. I add the class to the GC's root with std.gc.addRoot(). This should work, right (rather than storing it in an AA)?
Feb 19 2007