digitalmars.D - Member function pointers
- Manu (70/70) Jun 07 2013 So from my dconf talk, I detailed a nasty hack to handle member function
- Adam D. Ruppe (19/25) Jun 07 2013 delegates have two members, ptr and funcptr:
- Manu (11/32) Jun 07 2013 Indeed, I apologise for my ignorance! The properties are already there.....
- Adam D. Ruppe (103/107) Jun 07 2013 I just don't think they can be unless we change the visible type
- Manu (11/108) Jun 07 2013 I initially started with something like this. But look how much code it ...
- Adam D. Ruppe (5/10) Jun 07 2013 I just wanted to add type safety to a delegate; to get rid of the
- Michel Fortin (12/13) Jun 07 2013 Reminds me of something similar I implemented a while ago:
- Manu (8/18) Jun 07 2013 Precisely. The concept is already embedded inside of delegate, but deleg...
- Michel Fortin (12/15) Jun 07 2013 Delegates are not parametrized on the type of "this", which makes them
- Manu (7/19) Jun 07 2013 Actually, that's very true. Good point, and I think this is almost the k...
- Jacob Carlborg (6/27) Jun 09 2013 Can't we just say that a delegate declared as extern(C++) is a member
- Manu (10/42) Jun 10 2013 That seems pretty awkward to me. Basically a hack.
- Jacob Carlborg (10/18) Jun 10 2013 It depends on how you look at it. In D a delegate is a function pointer
- Manu (17/34) Jun 10 2013 A function pointer is a pointer. A delegate is a pointer to a function a...
- Jacob Carlborg (36/54) Jun 10 2013 I didn't know about that. Is that something that is in the language or
- Manu (19/78) Jun 10 2013 You supply 'this' at the time of calling. Read my OP.
- Jacob Carlborg (17/30) Jun 10 2013 Yes, exactly. It needs "this". It's the same thing as a delegate. It's
- Maxim Fomin (8/16) Jun 10 2013 I wouldn't say so. The fact that you pass context has nothing to
- Manu (23/54) Jun 10 2013 No, I'm not talking about delegates. I'm not talking about FastDelegate
- David Nadlinger (5/7) Jun 10 2013 Walter's very own calling convention. It is supposed to match
- Manu (5/12) Jun 10 2013 Indeed. I presume 'extern(C) void function()' is cdecl though?
- Simen Kjaeraas (8/14) Jun 10 2013 This is utter horseshit. Not that it's part of the complete type, nor ev...
- David Nadlinger (4/6) Jun 10 2013 This would encourage people to try something like
- Michel Fortin (30/46) Jun 10 2013 But a true member function pointer is also parametrized on the type of
- Jacob Carlborg (5/23) Jun 10 2013 Then he's asking for (more) type safe delegates and support for C++
- Manu (5/32) Jun 10 2013 I'm really not asking for delegates (although they could become more
- Jacob Carlborg (4/8) Jun 10 2013 I give up, I don't understand what you want.
- Manu (8/15) Jun 10 2013 ...a member function pointer syntax. It's not that complex.
- Jacob Carlborg (6/12) Jun 10 2013 What I don't understand is what this give you that a delegate doesn't.
- dennis luehring (3/13) Jun 10 2013 maybe he just don't need one to handle the this ptr because he wants to
- Jacob Carlborg (4/6) Jun 10 2013 How does he call a pointer to a member function without the "this" point...
- Steven Schveighoffer (9/14) Jun 10 2013 Like this:
- Manu (7/18) Jun 10 2013 It's just a pointer, 'this' is associated at the call site. And it's
- David Nadlinger (9/18) Jun 10 2013 Let me try to summarize it in code:
- Jacob Carlborg (4/11) Jun 10 2013 Why is this better than a delegate?
- Manu (2/14) Jun 10 2013 It's not 'better', it's different.
- Jacob Carlborg (12/24) Jun 10 2013 class A { void foo(); }
- Manu (3/35) Jun 10 2013 You can see how much work that is right? And it's still not typesafe.
- d coder via Digitalmars-d (10/44) May 27 2014 Greetings
- d coder via Digitalmars-d (18/18) May 27 2014 https://github.com/D-Programming-Language/dmd/pull/3181
- Dmitry Olshansky (44/54) Jun 10 2013 I decided to see how convenient can be a solution to auto-generate a
- David Nadlinger (6/9) Jun 10 2013 Another less intrusive option would be to just add
- Manu (8/15) Jun 10 2013 That would also do the business. Do you think that's less intrusive?
- David Nadlinger (13/23) Jun 10 2013 Less intrusive in the way that it is a minimal addition to the
- Michel Fortin (12/28) Jun 10 2013 It's inelegant, but it could work.
- Manu (2/33) Jun 10 2013 The ABI is the better part of half a century old...
- Walter Bright (2/3) Sep 09 2015 Sorry to say, your n.g. poster is back to its old tricks :-)
- Freddy (4/7) Sep 09 2015 On 6/10/2013
- Walter Bright (2/9) Sep 09 2015 Woops! I didn't notice. My reader sorts things based on the date of the ...
- Manu via Digitalmars-d (3/7) Sep 09 2015 We've resolved this issue since 6/10/2013 no? ;)
- Walter Bright (2/3) Sep 09 2015 :-)
- John Colvin (6/15) Sep 10 2015 In the web forum, this post shows up as having author
- Vladimir Panteleev (3/19) Sep 10 2015 Heh. My fault. Fixed (though it'll stick for that post in some
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (4/6) Sep 10 2015 Now the main index says: "Unexpected end of input when converting
- Vladimir Panteleev (4/10) Sep 10 2015 Doesn't happen here, so that's something local to you, almost
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (5/16) Sep 10 2015 Request URL:http://forum.dlang.org/
- Vladimir Panteleev (4/21) Sep 10 2015 Doesn't happen here, so that's something local to you, almost
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (4/6) Sep 10 2015 Yes, it was caused by cookies, but it wasn't local since it
- data man (3/6) Sep 10 2015 Correct a "D-Runtime" topic, please. It is not updated.
- Vladimir Panteleev (5/12) Sep 11 2015 Not sure what you mean, please clarify.
- Daniel Murphy (3/8) Jun 11 2013 For D, yes, and it would be awesome. For everything else, never ever ev...
- Walter Bright (2/4) Sep 09 2015 https://www.digitalmars.com/articles/b68.html
So from my dconf talk, I detailed a nasty hack to handle member function pointers in D. My approach is not portable, so I'd like to see an expression formalised in D, so this sort of interaction with C++ is possible, and also it may be useful in D code directly. I'm thinking something like this... Keen to hear thoughts. My approach was this: void function(T _this, ...args...); Explicit 'this' pointer; only works with ABI's that pass 'this' as the first integer argument. What I suggest is: void function(T this, ...args...); Note, I use keyword 'this' as the first argument. This is the key that distinguishes the expression as a member-function pointer rather than a typical function pointer. Calls through this function pointer would know to use the method calling convention rather than the static function calling convention. For 'extern(C++) void function(T this)', that would be to use the C++ 'thiscall' convention. I think this makes good sense, because other than the choice of calling convention, it really is just a 'function' in every other way. Now taken this as a declaration syntax, I think calls would be made via UFCS. T x; void function(T this) mp; mp(x); // I guess this is fine x.mp(); // but UFCS really makes this concept nice! So the final detail, is how to capture one of these member function pointers from within D... I initially thought about a syntax, but this is so niche, I don't think it warrants a syntax. So my current best idea is to introduce 2 properties to delegates, so that the function pointer (of this type) can be accessed via the delegate syntax. delegate d = &x.f; void function(T this) mp = d.funcPtr; An interesting side effect, is that 'delegate' could actually be understood as a strongly-typed small struct, whereas currently, it's just a magic thing: Given: RT delegate(A x, B y) d = &c.m; It would look like: struct delegate(C) { C thisPointer; RT function(C this, A x, B, y) funcPointer; } Currently, to get the instance or function pointers from a delegate, you need to do something like: delegate d; void** pd = cast(void**)&d; T instancePointer = cast(T)pd[0]; void function(T this) functionPointer = cast(RT function(T this))pd[1]; Casting through a void array like that is pretty horrible. Adding 2 properties to delegate to get either of those things can makes sense once it is possible to express the type of the function pointer, which would now be possible with the syntax above. So, I quite like the transparency introduced when a delegate can be explicitly described in the language. But there is one loose detail... void f() { void g() {} void delegate() d = &g; // delegate 'this' is a closure } I don't know a syntax to describe the type of a closure, so when a delegate is typed with a closure instead of a struct/class, what is 'C' in the struct template above? Thoughts? Is there reason to outright ban this sort of expression? I think this actually clarifies some details of the language, and reduces a currently 'magic' thing into a well-defined, strongly-typed concept. - Manu
Jun 07 2013
On Friday, 7 June 2013 at 23:22:03 UTC, Manu wrote:Currently, to get the instance or function pointers from a delegate, you need to do something like:delegates have two members, ptr and funcptr: http://dlang.org/function.html As a fun fact, if you modify druntime's allocator to be malloc(), you can use free(delegate.ptr) to manually manage closures, though this takes a lot of care to know if it actually should be freed or not. Anyway, the ptr member there is always void*, however, so at least one cast is required to actually use it. Perhaps the language could be extended to make this strongly typed, but then you'd have to change the whole visible type as assigning say, a closure to a delegate variable would need to be a different type than a class member; I guess this is what you're talking about though. idk, I've kinda wanted pointer to members before but I also think D's delegates being so versatile and interchangeable is totally boss.I don't know a syntax to describe the type of a closure, so when a delegate is typed with a closure instead of a struct/class, what is 'C' in the struct template above?That's a tricky one, perhaps it could be a tuple of the captured variables' type.
Jun 07 2013
On 8 June 2013 09:42, Adam D. Ruppe <destructionator gmail.com> wrote:On Friday, 7 June 2013 at 23:22:03 UTC, Manu wrote:Indeed, I apologise for my ignorance! The properties are already there... but they're not properly typed. idk, I've kinda wanted pointer to members before but I also think D'sCurrently, to get the instance or function pointers from a delegate, you need to do something like:delegates have two members, ptr and funcptr: http://dlang.org/function.html As a fun fact, if you modify druntime's allocator to be malloc(), you can use free(delegate.ptr) to manually manage closures, though this takes a lot of care to know if it actually should be freed or not. Anyway, the ptr member there is always void*, however, so at least one cast is required to actually use it. Perhaps the language could be extended to make this strongly typed, but then you'd have to change the whole visible type as assigning say, a closure to a delegate variable would need to be a different type than a class member; I guess this is what you're talking about though.delegates being so versatile and interchangeable is totally boss.I agree, a delegate is almost always what I want. But a delegate is really just a compound concept, and without a way to express it's fundamental parts, which in certain circumstances (like in my case) are useful on their own, then it feels like a bit of magic. I don't know a syntax to describe the type of a closure, so when aYeah, that was my initial feeling too... and I think it could be quite workable in that way.delegate is typed with a closure instead of a struct/class, what is 'C' in the struct template above?That's a tricky one, perhaps it could be a tuple of the captured variables' type.
Jun 07 2013
On Friday, 7 June 2013 at 23:54:55 UTC, Manu wrote:The properties are already there... but they're not properly typed.I just don't think they can be unless we change the visible type which isn't always what we want.... but, check this out: // this new type keeps track of the exact type of the pointer // and manages the delegate so we can cast with some sanity... struct PointerToMemberFunction(Class, Ret, T...) if(is(Class : Object)) { private Ret delegate(T) dg; property Class object() { return cast(Class) dg.ptr; } property void object(Class rhs) { dg.ptr = cast(void*) rhs; } Ret opCall(T t) { assert(dg.ptr !is null, "null this"); static if(is(Ret == void)) dg(t); else return dg(t); } } // this helps us construct the above template ptrToMember(alias blargh) { // I'm writing out the function template longhand // because I want to use blargh as a type and // dmd won't let me do it without an intermediate // dmd complains "type expected, not __traits" so we use // this to work around it template workaround(T) { alias workaround = T; } alias ObjectType = workaround!(__traits(parent, blargh)); auto ptrToMember(ObjectType a = null) { import std.traits; PointerToMemberFunction!( ObjectType, ReturnType!blargh, ParameterTypeTuple!blargh ) mem; mem.dg.funcptr = &blargh; mem.dg.ptr = cast(void*) a; return mem; } } actually i just realized maybe this should not be a function at all, so it is easy to use as a class member, without having to write an extra typeof(). That's probably more valuable than the initialiser which as you'll see below is optional anyway. Anyway, then you can use it like this: class A { void foo() {writeln("foo from ", name);} int bar(string s) {writeln("bar ",s," from ", name); return 10; } this(string n) { name = n; } string name; } class B : A { this(string n) { super(n); } override void foo() { writeln("derived foo from ", name); } } void main() { A a = new A("a"); B c = new B("c"); Object ob = a; auto ptr = ptrToMember!(B.foo)(c); // initialize the object here ptr(); ptr.object = a; ptr(); auto ptr2 = ptrToMember!(A.bar); // initialize to null.. ptr2.object = ptr.object; // can assign later ptr2("hey"); } And if you play around with the types there, you'll see the compile will fail if you do something uncool. Though the error messages sometimes suck, what the hell: "test2.d(58): Error: not a property ptr.object"... actually it is, but I was passing it an A when it required a B. That's a type mismatch, not a missing property. But whatever, at least it *did* fail to compile, so we have our type safety. And if I threw in an alias this on a getter property, we could assign these beasties to regular delegates too. Not half bad. But regular delegate assigning to this is prohibited because we can't be sure their context pointer is the right kind of class. This would be true if the compiler automatically did the ptrToMember!() too, so let's say we change &a.foo to return one of these strongly typed things instead of a void* delegate like it does now. auto ptr = &a.foo; // is ptr a void delegate() or a pointer to specifically a void() member of class A? That matters because if the former (current behavior), this compiles: ptr = { writeln("hello!"); }; but if the latter, that will not, it will complain that the this pointers are of mismatching type (or "not a property" lol). Of course, with alias this style behavior, you could explicitly write out void delegate() ptr = &a.foo; // ok, use looser type ptr = {...}; // perfectly fine So I guess we wouldn't be losing much, but since we both agree a delegate is almost always what we want, maybe the library solution of ptrToMember is better to keep auto in a Just Works state. I'm presuming you're already doing something similar for your C++ interop, if not, I'm pretty sure this same idea would work there too, at least to a 'good enough' state, even if not technically portable.Yeah, that was my initial feeling too... and I think it could be quite workable in that way.Aye, and this would require the compiler's help. Can't hit 'good enough' on that with templates.
Jun 07 2013
On 8 June 2013 10:24, Adam D. Ruppe <destructionator gmail.com> wrote:On Friday, 7 June 2013 at 23:54:55 UTC, Manu wrote:I initially started with something like this. But look how much code it is! I actually deleted it all and went for my non-portable hack. My implementation was different. You've basically wrapped up a delegate, and made something that emulates a delegate (I'm not sure why?). I don't want a delegate, I want a function pointer. So my solution was similar, but wrapped up a function pointer and aliased a delegate to the correct type, then created a local delegate populating with 'this' and the function at the call-site... But it's all crap! It's really just abusing a delegate to get at the concept it embed's which doesn't have a proper expression.The properties are already there... but they're not properly typed.I just don't think they can be unless we change the visible type which isn't always what we want.... but, check this out: // this new type keeps track of the exact type of the pointer // and manages the delegate so we can cast with some sanity... struct PointerToMemberFunction(Class, Ret, T...) if(is(Class : Object)) { private Ret delegate(T) dg; property Class object() { return cast(Class) dg.ptr; } property void object(Class rhs) { dg.ptr = cast(void*) rhs; } Ret opCall(T t) { assert(dg.ptr !is null, "null this"); static if(is(Ret == void)) dg(t); else return dg(t); } } // this helps us construct the above template ptrToMember(alias blargh) { // I'm writing out the function template longhand // because I want to use blargh as a type and // dmd won't let me do it without an intermediate // dmd complains "type expected, not __traits" so we use // this to work around it template workaround(T) { alias workaround = T; } alias ObjectType = workaround!(__traits(parent, blargh)); auto ptrToMember(ObjectType a = null) { import std.traits; PointerToMemberFunction!( ObjectType, ReturnType!blargh, ParameterTypeTuple!blargh ) mem; mem.dg.funcptr = &blargh; mem.dg.ptr = cast(void*) a; return mem; } } actually i just realized maybe this should not be a function at all, so it is easy to use as a class member, without having to write an extra typeof(). That's probably more valuable than the initialiser which as you'll see below is optional anyway. Anyway, then you can use it like this: class A { void foo() {writeln("foo from ", name);} int bar(string s) {writeln("bar ",s," from ", name); return 10; } this(string n) { name = n; } string name; } class B : A { this(string n) { super(n); } override void foo() { writeln("derived foo from ", name); } } void main() { A a = new A("a"); B c = new B("c"); Object ob = a; auto ptr = ptrToMember!(B.foo)(c); // initialize the object here ptr(); ptr.object = a; ptr(); auto ptr2 = ptrToMember!(A.bar); // initialize to null.. ptr2.object = ptr.object; // can assign later ptr2("hey"); } And if you play around with the types there, you'll see the compile will fail if you do something uncool. Though the error messages sometimes suck, what the hell: "test2.d(58): Error: not a property ptr.object"... actually it is, but I was passing it an A when it required a B. That's a type mismatch, not a missing property. But whatever, at least it *did* fail to compile, so we have our type safety. And if I threw in an alias this on a getter property, we could assign these beasties to regular delegates too. Not half bad. But regular delegate assigning to this is prohibited because we can't be sure their context pointer is the right kind of class. This would be true if the compiler automatically did the ptrToMember!() too, so let's say we change &a.foo to return one of these strongly typed things instead of a void* delegate like it does now. auto ptr = &a.foo; // is ptr a void delegate() or a pointer to specifically a void() member of class A? That matters because if the former (current behavior), this compiles: ptr = { writeln("hello!"); }; but if the latter, that will not, it will complain that the this pointers are of mismatching type (or "not a property" lol). Of course, with alias this style behavior, you could explicitly write out void delegate() ptr = &a.foo; // ok, use looser type ptr = {...}; // perfectly fine So I guess we wouldn't be losing much, but since we both agree a delegate is almost always what we want, maybe the library solution of ptrToMember is better to keep auto in a Just Works state. I'm presuming you're already doing something similar for your C++ interop, if not, I'm pretty sure this same idea would work there too, at least to a 'good enough' state, even if not technically portable.
Jun 07 2013
On Saturday, 8 June 2013 at 01:11:46 UTC, Manu wrote:I initially started with something like this. But look how much code it is!Yeah...You've basically wrapped up a delegate, and made something that emulates a delegate (I'm not sure why?).I just wanted to add type safety to a delegate; to get rid of the visible cast(void*) and vice versa, to see what it would look like.
Jun 07 2013
On 2013-06-07 23:21:53 +0000, Manu <turkeyman gmail.com> said:Thoughts?Reminds me of something similar I implemented a while ago: http://michelf.ca/projects/d-objc/syntax/#selector-literals Not only I think member function pointers are doable, but I think they're solely missing. There have been situations where I'd have used them but instead had to hack my way using a delegate. That was to build a bridge for Objective-C (before I decided to hack the compiler). I'd guess you're doing something of the sort too? -- Michel Fortin michel.fortin michelf.ca http://michelf.ca/
Jun 07 2013
On 8 June 2013 09:48, Michel Fortin <michel.fortin michelf.ca> wrote:On 2013-06-07 23:21:53 +0000, Manu <turkeyman gmail.com> said: Thoughts?Precisely. The concept is already embedded inside of delegate, but delegate is framed like a piece of magic, rather than a well defined compound of more primitive pieces. Those primitive pieces would be useful in certain cases (like mine, and yours). I think the only missing detail is a way to express a 'thiscall' function pointer, which I believe my suggestion satisfies quite nicely.Reminds me of something similar I implemented a while ago: http://michelf.ca/projects/d-**objc/syntax/#selector-literals<http://michelf.ca/projects/d-objc/syntax/#selector-literals> Not only I think member function pointers are doable, but I think they're solely missing. There have been situations where I'd have used them but instead had to hack my way using a delegate. That was to build a bridge for Objective-C (before I decided to hack the compiler). I'd guess you're doing something of the sort too?
Jun 07 2013
On 2013-06-07 23:57:40 +0000, Manu <turkeyman gmail.com> said:Precisely. The concept is already embedded inside of delegate, but delegate is framed like a piece of magic, rather than a well defined compound of more primitive pieces.Delegates are not parametrized on the type of "this", which makes them easier to move around. I would not change delegates. But function pointers with a "this" parameter would be useful. You can achieve this using a template struct containing a pointer and a call method: the call method would generate a local delegate variable from the pointer and and call it. What you can't do without compiler support is get such a pointer in a type-safe manner. -- Michel Fortin michel.fortin michelf.ca http://michelf.ca/
Jun 07 2013
On 8 June 2013 12:29, Michel Fortin <michel.fortin michelf.ca> wrote:On 2013-06-07 23:57:40 +0000, Manu <turkeyman gmail.com> said: Precisely. The concept is already embedded inside of delegate, butActually, that's very true. Good point, and I think this is almost the key distinction. But function pointers with a "this" parameter would be useful. You candelegate is framed like a piece of magic, rather than a well defined compound of more primitive pieces.Delegates are not parametrized on the type of "this", which makes them easier to move around. I would not change delegates.achieve this using a template struct containing a pointer and a call method: the call method would generate a local delegate variable from the pointer and and call it. What you can't do without compiler support is get such a pointer in a type-safe manner.Yup, this is what I originally did. It's big and ugly, I didn't like it, and deleted it. I think the syntax I suggest is simple and obvious, and naturally, typesafe.
Jun 07 2013
On 2013-06-08 01:21, Manu wrote:So from my dconf talk, I detailed a nasty hack to handle member function pointers in D. My approach is not portable, so I'd like to see an expression formalised in D, so this sort of interaction with C++ is possible, and also it may be useful in D code directly. I'm thinking something like this... Keen to hear thoughts. My approach was this: void function(T _this, ...args...); Explicit 'this' pointer; only works with ABI's that pass 'this' as the first integer argument. What I suggest is: void function(T this, ...args...); Note, I use keyword 'this' as the first argument. This is the key that distinguishes the expression as a member-function pointer rather than a typical function pointer. Calls through this function pointer would know to use the method calling convention rather than the static function calling convention. For 'extern(C++) void function(T this)', that would be to use the C++ 'thiscall' convention. I think this makes good sense, because other than the choice of calling convention, it really is just a 'function' in every other way.Can't we just say that a delegate declared as extern(C++) is a member function? Or do you want to use member functions without connecting to C++ as well? -- /Jacob Carlborg
Jun 09 2013
On 10 June 2013 16:50, Jacob Carlborg <doob me.com> wrote:On 2013-06-08 01:21, Manu wrote:That seems pretty awkward to me. Basically a hack. A function pointer is not a delegate, so I don't see why that should be used to describe one. Also, extern(C++) delegates are useful too in their own right Or do you want to use member functions without connecting to C++ as well? I haven't needed to yet... but that doesn't mean it might not be useful. It would probably be used in D for tight binding with other systems. AngelScript binds to native code with member function pointers... just off the top of my head.So from my dconf talk, I detailed a nasty hack to handle member function pointers in D. My approach is not portable, so I'd like to see an expression formalised in D, so this sort of interaction with C++ is possible, and also it may be useful in D code directly. I'm thinking something like this... Keen to hear thoughts. My approach was this: void function(T _this, ...args...); Explicit 'this' pointer; only works with ABI's that pass 'this' as the first integer argument. What I suggest is: void function(T this, ...args...); Note, I use keyword 'this' as the first argument. This is the key that distinguishes the expression as a member-function pointer rather than a typical function pointer. Calls through this function pointer would know to use the method calling convention rather than the static function calling convention. For 'extern(C++) void function(T this)', that would be to use the C++ 'thiscall' convention. I think this makes good sense, because other than the choice of calling convention, it really is just a 'function' in every other way.Can't we just say that a delegate declared as extern(C++) is a member function?
Jun 10 2013
On 2013-06-10 09:23, Manu wrote:That seems pretty awkward to me. Basically a hack. A function pointer is not a delegate, so I don't see why that should be used to describe one.It depends on how you look at it. In D a delegate is a function pointer with a context pointer. In C++ a pointer to a member function is basically the same, the context pointer is just passed separately.Also, extern(C++) delegates are useful too in their own rightTo do what? As far as I know C++ doesn't have anything corresponding to a D delegate.I haven't needed to yet... but that doesn't mean it might not be useful. It would probably be used in D for tight binding with other systems. AngelScript binds to native code with member function pointers... just off the top of my head.Actually I don't see why you can't use a delegate for this. The only difference is that it won't be virtual. -- /Jacob Carlborg
Jun 10 2013
On 10 June 2013 18:04, Jacob Carlborg <doob me.com> wrote:On 2013-06-10 09:23, Manu wrote: That seems pretty awkward to me. Basically a hack.A function pointer is a pointer. A delegate is a pointer to a function and a context pointer, ie, 2 pointers. A pointer to a method is just a pointer to a function, but it's a special function which receives a 'this' argument with a special calling convention. It's definitely useful to be able to express a 'thiscall' function pointer. Also, extern(C++) delegates are useful too in their own rightA function pointer is not a delegate, so I don't see why that should be used to describe one.It depends on how you look at it. In D a delegate is a function pointer with a context pointer. In C++ a pointer to a member function is basically the same, the context pointer is just passed separately.C++ has FastDelegate, which I use to interact with D delegates all the time! ;) extern(C++) delegate is required to specify the appropriate calling convention, otherwise it's just a delegate like usual. I haven't needed to yet... but that doesn't mean it might not be useful.To do what? As far as I know C++ doesn't have anything corresponding to a D delegate.I'm just trying to show that sometimes you don't want a delegate, you just want a function pointer. delegate's contain the function pointer I'm after, so I can access it indirectly, but it's just not so useful. It's not typed (is void*), and you can't call through it.It would probably be used in D for tight binding with other systems. AngelScript binds to native code with member function pointers... just off the top of my head.Actually I don't see why you can't use a delegate for this. The only difference is that it won't be virtual.
Jun 10 2013
On 2013-06-10 11:45, Manu wrote:A function pointer is a pointer. A delegate is a pointer to a function and a context pointer, ie, 2 pointers. A pointer to a method is just a pointer to a function, but it's a special function which receives a 'this' argument with a special calling convention. It's definitely useful to be able to express a 'thiscall' function pointer.It's not very useful without the context pointer, i.e. "this".Also, extern(C++) delegates are useful too in their own right To do what? As far as I know C++ doesn't have anything corresponding to a D delegate. C++ has FastDelegate, which I use to interact with D delegates all the time! ;)I didn't know about that. Is that something that is in the language or standard library?extern(C++) delegate is required to specify the appropriate calling convention, otherwise it's just a delegate like usual.I see.I'm just trying to show that sometimes you don't want a delegate, you just want a function pointer.Then use a function pointer.delegate's contain the function pointer I'm after, so I can access it indirectly, but it's just not so useful. It's not typed (is void*), and you can't call through it.The function pointer of a delegate is typed, it's the context pointer that is void*. Sorry, I'm just trying to understand what you're doing, what problems you have. You can compose and decompose delegates using its built-in properties "ptr" and "funcptr". You can do something like: class Foo { int i; void a () { writeln("Foo.a i=", i); } void b () { writeln("Foo.b i=", i); } } void main () { auto f1 = new Foo; f1.i = 3; auto dg = &f1.a; dg(); auto f2 = new Foo; f2.i = 4; dg.ptr = cast(void*) f2; dg(); dg.funcptr = &Foo.b; dg(); } The only thing that doesn't work with the above is if I change the context pointer to a subclass of Foo which overrides the method I want to call. It will still call the method in Foo unless I change "funcptr". -- /Jacob Carlborg
Jun 10 2013
On 10 June 2013 21:35, Jacob Carlborg <doob me.com> wrote:On 2013-06-10 11:45, Manu wrote: A function pointer is a pointer. A delegate is a pointer to a functionYou supply 'this' at the time of calling. Read my OP. Also, extern(C++) delegates are useful too in their own rightand a context pointer, ie, 2 pointers. A pointer to a method is just a pointer to a function, but it's a special function which receives a 'this' argument with a special calling convention. It's definitely useful to be able to express a 'thiscall' function pointer.It's not very useful without the context pointer, i.e. "this".It's Don's work of art. It's also how I came to find out about D in the first place ;) extern(C++) delegate is required to specify the appropriate callingTo do what? As far as I know C++ doesn't have anything corresponding to a D delegate. C++ has FastDelegate, which I use to interact with D delegates all the time! ;)I didn't know about that. Is that something that is in the language or standard library?There's no way to specify to use the 'thiscall' calling convention. What I propose is a syntax that would describe a member function pointer, and imply the appropriate calling convention. delegate's contain the function pointer I'm after, so I can access itconvention, otherwise it's just a delegate like usual.I see. I'm just trying to show that sometimes you don't want a delegate, youjust want a function pointer.Then use a function pointer.I wouldn't say that doesn't work, I'd say that works perfectly. A delegate is just a 'this' and function pair. If you change 'this', there's no reason the function should change. funcptr pretends to be typed, but the type is just wrong. In your example, the type is 'void function()', it should be 'void function(Foo this)'. So it's actually a lie. You can't call it. I'm not sure why it's typed at all... just a crash waiting to happen. So what I'm suggesting is a syntax to express a member function pointer, and then it could be properly typed.indirectly, but it's just not so useful. It's not typed (is void*), and you can't call through it.The function pointer of a delegate is typed, it's the context pointer that is void*. Sorry, I'm just trying to understand what you're doing, what problems you have. You can compose and decompose delegates using its built-in properties "ptr" and "funcptr". You can do something like: class Foo { int i; void a () { writeln("Foo.a i=", i); } void b () { writeln("Foo.b i=", i); } } void main () { auto f1 = new Foo; f1.i = 3; auto dg = &f1.a; dg(); auto f2 = new Foo; f2.i = 4; dg.ptr = cast(void*) f2; dg(); dg.funcptr = &Foo.b; dg(); } The only thing that doesn't work with the above is if I change the context pointer to a subclass of Foo which overrides the method I want to call. It will still call the method in Foo unless I change "funcptr".
Jun 10 2013
On 2013-06-10 14:36, Manu wrote:You supply 'this' at the time of calling. Read my OP.Yes, exactly. It needs "this". It's the same thing as a delegate. It's just that with the delegate the context pointer and function pointer is combined. A function pointer (member or free) is useless if it's not called.It's Don's work of art. It's also how I came to find out about D in the first place ;)I see.There's no way to specify to use the 'thiscall' calling convention. What I propose is a syntax that would describe a member function pointer, and imply the appropriate calling convention.Right. I suggested a different syntax, but you want to reserve that syntax for something that match a library implementation, that's not even in the standard. It's like saying I want int[] to match MyIntArray implemented in C++.funcptr pretends to be typed, but the type is just wrong. In your example, the type is 'void function()', it should be 'void function(Foo this)'."void function()" is part of the complete type. It becomes complete with the context pointer.So it's actually a lie. You can't call it. I'm not sure why it's typed at all... just a crash waiting to happen.You can put a free function in a delegate and call it through the delegate. I guess you don't want that to be possible either.So what I'm suggesting is a syntax to express a member function pointer, and then it could be properly typed.I don't think there's anything wrong with supporting C++ member function pointers but I don't think we need to add new syntax for it. -- /Jacob Carlborg
Jun 10 2013
On Monday, 10 June 2013 at 12:53:34 UTC, Jacob Carlborg wrote:On 2013-06-10 14:36, Manu wrote:I wouldn't say so. The fact that you pass context has nothing to do with determining type. For example, you can pass A class instead of B to B method, but B method would still keep its original type. So yes, there is a type problem in language when function taking some parameter is declared as having no such parameter. This is a serious hole in type system.funcptr pretends to be typed, but the type is just wrong. In your example, the type is 'void function()', it should be 'void function(Foo this)'."void function()" is part of the complete type. It becomes complete with the context pointer.
Jun 10 2013
On 10 June 2013 22:53, Jacob Carlborg <doob me.com> wrote:On 2013-06-10 14:36, Manu wrote: You supply 'this' at the time of calling. Read my OP.No, I'm not talking about delegates. I'm not talking about FastDelegate (that was an aside when you commented that C++ has no concept of delegate). I'm just talking about function pointers. Not sure where you get this analogy from? funcptr pretends to be typed, but the type is just wrong. In yourYes, exactly. It needs "this". It's the same thing as a delegate. It's just that with the delegate the context pointer and function pointer is combined. A function pointer (member or free) is useless if it's not called. It's Don's work of art. It's also how I came to find out about D in thefirst place ;)I see. There's no way to specify to use the 'thiscall' calling convention.What I propose is a syntax that would describe a member function pointer, and imply the appropriate calling convention.Right. I suggested a different syntax, but you want to reserve that syntax for something that match a library implementation, that's not even in the standard. It's like saying I want int[] to match MyIntArray implemented in C++.The context pointer type is not present in the type. So the function can't be used/called. It also doesn't know how to call it. What's the calling convention for 'void function()'? cdecl? So it's actually a lie. You can't call it. I'm not sure why it's typedexample, the type is 'void function()', it should be 'void function(Foo this)'."void function()" is part of the complete type. It becomes complete with the context pointer.A free function? Like a static function? You can assign it, but it'll crash. Free functions are cdecl, methods are thiscall. If you know the ABI and it receives 'this' as the first integer argument, you can fabricate a compatible signature and it won't crash, but it's not portable. This is my whole point about the type-safety. If we create an expression to describe a method pointer, then we can actually do it safely and portably. So what I'm suggesting is a syntax to express a member function pointer,at all... just a crash waiting to happen.You can put a free function in a delegate and call it through the delegate. I guess you don't want that to be possible either.I'm not suggesting supporting 'C++ member function pointers', they are completely bat-shit crazy. I'm suggesting a distinctly D way. They will be useful when interfacing C++, and also on their own, and unlike C++, they won't be totally mental.and then it could be properly typed.I don't think there's anything wrong with supporting C++ member function pointers but I don't think we need to add new syntax for it.
Jun 10 2013
On Monday, 10 June 2013 at 13:45:37 UTC, Manu wrote:What's the calling convention for 'void function()'? cdecl?Walter's very own calling convention. It is supposed to match cdecl everywhere but x86, but has the argument order reversed. On x86, it's a custom one that's similar to stdcall in some ways. David
Jun 10 2013
On 10 June 2013 23:49, David Nadlinger <code klickverbot.at> wrote:On Monday, 10 June 2013 at 13:45:37 UTC, Manu wrote:Indeed. I presume 'extern(C) void function()' is cdecl though? Likewise 'extern(C++) void function(T this)' would be 'thiscall', and 'void function(T this)' would be whatever D's method calling convention happens to be.What's the calling convention for 'void function()'? cdecl?Walter's very own calling convention. It is supposed to match cdecl everywhere but x86, but has the argument order reversed. On x86, it's a custom one that's similar to stdcall in some ways.
Jun 10 2013
On Mon, 10 Jun 2013 14:53:33 +0200, Jacob Carlborg <doob me.com> wrote:On 2013-06-10 14:36, Manu wrote:This is utter horseshit. Not that it's part of the complete type, nor even that it becomes complete with the context pointer (though that is highly dubious at best), but the type of funcptr. It's a disgrace, simple as that. It should either be typeless, or it should take a void* as its first argument. void* means 'magic ahead', so it would be kinda ok. -- Simenfuncptr pretends to be typed, but the type is just wrong. In your example, the type is 'void function()', it should be 'void function(Foo this)'."void function()" is part of the complete type. It becomes complete with the context pointer.
Jun 10 2013
On Monday, 10 June 2013 at 20:31:32 UTC, Simen Kjaeraas wrote:or it should take a void* as its first argument. void* means 'magic ahead', so it would be kinda ok.This would encourage people to try something like dg.funcptr(dg.ptr, ...), which is not correct ABI-wise. David
Jun 10 2013
On 2013-06-10 08:04:43 +0000, Jacob Carlborg <doob me.com> said:On 2013-06-10 09:23, Manu wrote:But a true member function pointer is also parametrized on the type of this, unlike a delegate, letting you change the object pointer in a type-safe manner. (And implementation-wise, C++ function pointers can be really complicated beasts in order to support virtual calling and multiple/virtual inheritance. sizeof can even change depending on the type of "this". That's not what you want in D.)That seems pretty awkward to me. Basically a hack. A function pointer is not a delegate, so I don't see why that should be used to describe one.It depends on how you look at it. In D a delegate is a function pointer with a context pointer. In C++ a pointer to a member function is basically the same, the context pointer is just passed separately.Type-safety. I mean, you can do this if you want: auto funcptr = &Object.toString; auto object = new Object; // now call our function using object string delegate() deleg; deleg.ptr = cast(void*)object; deleg.funcptr = funcptr; but this is not type-safe: the funcptr type ("string function()") is actually wrong (it'll only work if called from a delegate) and the object pointer the in the delegate is a void*. All Manu is asking is that funcptr is of a correct type so you can call it directly by supplying "this" as an argument, like this: funcptr(object); The problem is that this "correct type" for the function pointer does not exist currently. Calling a member function uses a different ABI, so the type needs to know somehow its a pointer to a member function (and that its first parameter is "this"), otherwise the generated code at the call site will be all wrong. -- Michel Fortin michel.fortin michelf.ca http://michelf.ca/I haven't needed to yet... but that doesn't mean it might not be useful. It would probably be used in D for tight binding with other systems. AngelScript binds to native code with member function pointers... just off the top of my head.Actually I don't see why you can't use a delegate for this. The only difference is that it won't be virtual.
Jun 10 2013
On 2013-06-10 14:32, Michel Fortin wrote:Type-safety. I mean, you can do this if you want: auto funcptr = &Object.toString; auto object = new Object; // now call our function using object string delegate() deleg; deleg.ptr = cast(void*)object; deleg.funcptr = funcptr; but this is not type-safe: the funcptr type ("string function()") is actually wrong (it'll only work if called from a delegate) and the object pointer the in the delegate is a void*. All Manu is asking is that funcptr is of a correct type so you can call it directly by supplying "this" as an argument, like this: funcptr(object); The problem is that this "correct type" for the function pointer does not exist currently. Calling a member function uses a different ABI, so the type needs to know somehow its a pointer to a member function (and that its first parameter is "this"), otherwise the generated code at the call site will be all wrong.Then he's asking for (more) type safe delegates and support for C++ member function pointers. -- /Jacob Carlborg
Jun 10 2013
On 10 June 2013 22:56, Jacob Carlborg <doob me.com> wrote:On 2013-06-10 14:32, Michel Fortin wrote: Type-safety. I mean, you can do this if you want:I'm really not asking for delegates (although they could become more typesafe given my suggestion), just a member function pointer. And not C++ style as you say, my suggestion is much simpler than that, and would fit nicely in D.auto funcptr = &Object.toString; auto object = new Object; // now call our function using object string delegate() deleg; deleg.ptr = cast(void*)object; deleg.funcptr = funcptr; but this is not type-safe: the funcptr type ("string function()") is actually wrong (it'll only work if called from a delegate) and the object pointer the in the delegate is a void*. All Manu is asking is that funcptr is of a correct type so you can call it directly by supplying "this" as an argument, like this: funcptr(object); The problem is that this "correct type" for the function pointer does not exist currently. Calling a member function uses a different ABI, so the type needs to know somehow its a pointer to a member function (and that its first parameter is "this"), otherwise the generated code at the call site will be all wrong.Then he's asking for (more) type safe delegates and support for C++ member function pointers.
Jun 10 2013
On 2013-06-10 15:47, Manu wrote:I'm really not asking for delegates (although they could become more typesafe given my suggestion), just a member function pointer. And not C++ style as you say, my suggestion is much simpler than that, and would fit nicely in D.I give up, I don't understand what you want. -- /Jacob Carlborg
Jun 10 2013
On 11 June 2013 00:43, Jacob Carlborg <doob me.com> wrote:On 2013-06-10 15:47, Manu wrote: I'm really not asking for delegates (although they could become more...a member function pointer syntax. It's not that complex. My suggestion is: void function(T this) funcptr; This is a function pointer (not a delegate), but using keyword 'this' gives the critical detail to the compiler that it's a member function pointer, and to use the appropriate calling convention when making calls through this pointer. UFCS makes it awesome.typesafe given my suggestion), just a member function pointer. And not C++ style as you say, my suggestion is much simpler than that, and would fit nicely in D.I give up, I don't understand what you want.
Jun 10 2013
On 2013-06-10 17:36, Manu wrote:My suggestion is: void function(T this) funcptr; This is a function pointer (not a delegate), but using keyword 'this' gives the critical detail to the compiler that it's a member function pointer, and to use the appropriate calling convention when making calls through this pointer. UFCS makes it awesome.What I don't understand is what this give you that a delegate doesn't. You need the "this" pointer to call the function pointer anyway. With a delegate it's bundled. -- /Jacob Carlborg
Jun 10 2013
Am 10.06.2013 18:28, schrieb Jacob Carlborg:On 2013-06-10 17:36, Manu wrote:maybe he just don't need one to handle the this ptr because he wants to call several/hundrets of member-functions?My suggestion is: void function(T this) funcptr; This is a function pointer (not a delegate), but using keyword 'this' gives the critical detail to the compiler that it's a member function pointer, and to use the appropriate calling convention when making calls through this pointer. UFCS makes it awesome.What I don't understand is what this give you that a delegate doesn't. You need the "this" pointer to call the function pointer anyway. With a delegate it's bundled.
Jun 10 2013
On 2013-06-10 18:38, dennis luehring wrote:maybe he just don't need one to handle the this ptr because he wants to call several/hundrets of member-functions?How does he call a pointer to a member function without the "this" pointer? -- /Jacob Carlborg
Jun 10 2013
On Mon, 10 Jun 2013 12:45:12 -0400, Jacob Carlborg <doob me.com> wrote:On 2013-06-10 18:38, dennis luehring wrote:Like this: void callRandomMember(C[] objs, memberPointerToCMethod p) { objs[random(0, objs.length)].p(); } Essentially, you bind at call time to form a delegate. But the member function pointer's 'this' must be strongly typed. -Stevemaybe he just don't need one to handle the this ptr because he wants to call several/hundrets of member-functions?How does he call a pointer to a member function without the "this" pointer?
Jun 10 2013
On 11 June 2013 02:28, Jacob Carlborg <doob me.com> wrote:On 2013-06-10 17:36, Manu wrote: My suggestion is: void function(T this) funcptr;It's just a pointer, 'this' is associated at the call site. And it's strongly typed. If you don't want a bundle, why be forced to use a bundled type? Consider this, why would you ever want an int* when you can have an int[]? We could remove the syntax for int*, and make it only accessible via int[].ptr... and make: is(typeof(int[].ptr) == size_t)? :)This is a function pointer (not a delegate), but using keyword 'this' gives the critical detail to the compiler that it's a member function pointer, and to use the appropriate calling convention when making calls through this pointer. UFCS makes it awesome.What I don't understand is what this give you that a delegate doesn't. You need the "this" pointer to call the function pointer anyway. With a delegate it's bundled.
Jun 10 2013
On Monday, 10 June 2013 at 14:43:50 UTC, Jacob Carlborg wrote:On 2013-06-10 15:47, Manu wrote:Let me try to summarize it in code: --- class A { void foo(); } auto memberFun = (&A.foo).funcptr; auto a = new A; memberFun(a); --- DavidI'm really not asking for delegates (although they could become more typesafe given my suggestion), just a member function pointer. And not C++ style as you say, my suggestion is much simpler than that, and would fit nicely in D.I give up, I don't understand what you want.
Jun 10 2013
On 2013-06-10 17:40, David Nadlinger wrote:Let me try to summarize it in code: --- class A { void foo(); } auto memberFun = (&A.foo).funcptr; auto a = new A; memberFun(a); ---Why is this better than a delegate? -- /Jacob Carlborg
Jun 10 2013
On 11 June 2013 02:26, Jacob Carlborg <doob me.com> wrote:On 2013-06-10 17:40, David Nadlinger wrote: Let me try to summarize it in code:It's not 'better', it's different.--- class A { void foo(); } auto memberFun = (&A.foo).funcptr; auto a = new A; memberFun(a); ---Why is this better than a delegate?
Jun 10 2013
On 2013-06-10 18:34, Manu wrote:On 11 June 2013 02:26, Jacob Carlborg <doob me.com <mailto:doob me.com>> wrote: On 2013-06-10 17:40, David Nadlinger wrote: Let me try to summarize it in code: --- class A { void foo(); } auto memberFun = (&A.foo).funcptr; auto a = new A; memberFun(a); --- Why is this better than a delegate? It's not 'better', it's different.class A { void foo(); } auto memberFun = (&A.foo).funcptr; auto a = new A; void delegate () dg; dg.funcptr = memberFun; dg.ptr = cast(void*) a; dg(); The details can be hidden in a function call. Sure, a delegate could be type safe but still don't see the point. -- /Jacob Carlborg
Jun 10 2013
On 11 June 2013 02:43, Jacob Carlborg <doob me.com> wrote:On 2013-06-10 18:34, Manu wrote:You can see how much work that is right? And it's still not typesafe. It's totally a hack.On 11 June 2013 02:26, Jacob Carlborg <doob me.com <mailto:doob me.com>> wrote: On 2013-06-10 17:40, David Nadlinger wrote: Let me try to summarize it in code: --- class A { void foo(); } auto memberFun = (&A.foo).funcptr; auto a = new A; memberFun(a); --- Why is this better than a delegate? It's not 'better', it's different.class A { void foo(); } auto memberFun = (&A.foo).funcptr; auto a = new A; void delegate () dg; dg.funcptr = memberFun; dg.ptr = cast(void*) a; dg(); The details can be hidden in a function call. Sure, a delegate could be type safe but still don't see the point.
Jun 10 2013
On Mon, Jun 10, 2013 at 10:13 PM, Jacob Carlborg <doob me.com> wrote:On 2013-06-10 18:34, Manu wrote:Greetings Apologies for bringing up this year old thread. With https://github.com/D-Programming-Language/dmd/pull/3181 getting merged, it is no longer feasible to directly assign dg.funcptr (which is not an lvalue now). The problem is that the code suggested by David also does not work. Is there an alternative? Regards - PuneetOn 11 June 2013 02:26, Jacob Carlborg <doob me.com <mailto:doob me.com>> wrote: On 2013-06-10 17:40, David Nadlinger wrote: Let me try to summarize it in code: --- class A { void foo(); } auto memberFun = (&A.foo).funcptr; auto a = new A; memberFun(a); --- Why is this better than a delegate? It's not 'better', it's different.class A { void foo(); } auto memberFun = (&A.foo).funcptr; auto a = new A; void delegate () dg; dg.funcptr = memberFun; dg.ptr = cast(void*) a; dg(); The details can be hidden in a function call. Sure, a delegate could be type safe but still don't see the point. -- /Jacob Carlborg
May 27 2014
https://github.com/D-Programming-Language/dmd/pull/3181 Daniel asked me to use this. And it works. Use something like: union U { void delegate(int) dg; struct { void* ptr; void function(int) funcptr; } } U u; u.dg = dg; u.funcptr = ...; u.ptr = ...; Regards - Puneet
May 27 2014
On Tuesday, 27 May 2014 at 12:21:40 UTC, d coder wrote:https://github.com/D-Programming-Language/dmd/pull/3181 Daniel asked me to use this. And it works. Use something like: union U { void delegate(int) dg; struct { void* ptr; void function(int) funcptr; } } U u; u.dg = dg; u.funcptr = ...; u.ptr = ...; Regards - PuneetWhat's the current state of this? I'm in need of such behavior for win32 interop. I'm thinking that one can make the above code more general by using it in a mixin and automatically generating the funcptr signature: import std.stdio; import std.concurrency; extern (C) int getch(); import std.string; template FancyDelegate(O, D) { const char[] FancyDelegate = "union "~O.stringof~"Delegate { "~D.stringof~" dg; struct { "~O.stringof~"* ptr; "~D.stringof.replace("delegate(", "function("~O.stringof~",").replace(",)", ")")~" funcptr; } }"; //const char[] FancyDelegate = "union "~O.stringof~"Delegate { "~D.stringof~" dg; struct { "~O.stringof~"* ptr; "~D.stringof.replace("delegate(", "function(")~" funcptr; } }"; } class X { public int z = 2; public void foo(int x) { //writeln(this.z*x); writeln(x); } } void delegate(int) dg; mixin(FancyDelegate!(X, typeof(dg))); void main() { auto xX = new X(); XDelegate x; x.dg = &xX.foo; //x.dg(3); x.ptr = &xX; x.funcptr(xX, 5); //x.funcptr(5); getch(); } Unfortunately this fails when entering the function. I've tried various things(passing &xX, etc..., passing nothing(the comments, etc.) I thought a delegate, when called, was called like a member function? It seems that a delegate is some magic black box that we can't emulate in any way shape or form due to the calling conventions used?
Sep 09 2015
On Wednesday, 9 September 2015 at 18:33:41 UTC, Prudence wrote:On Tuesday, 27 May 2014 at 12:21:40 UTC, d coder wrote:struct S { void fun() { writeln("fun" ); } } class C { void fun() { writeln("fun" ); } } void main(string[] args) { S s; void delegate() fn1 = &s.fun; fn1(); C c = new C(); void delegate() fn2 = &c.fun; fn2(); void delegate() fn3; fn3.ptr = cast(void*)&s; fn3.funcptr = &S.fun; fn3(); void delegate() fn4; fn4.ptr = cast(void*)c; fn4.funcptr = &C.fun; fn4(); }[...]What's the current state of this? I'm in need of such behavior for win32 interop. I'm thinking that one can make the above code more general by using it in a mixin and automatically generating the funcptr signature: import std.stdio; import std.concurrency; extern (C) int getch(); import std.string; template FancyDelegate(O, D) { const char[] FancyDelegate = "union "~O.stringof~"Delegate { "~D.stringof~" dg; struct { "~O.stringof~"* ptr; "~D.stringof.replace("delegate(", "function("~O.stringof~",").replace(",)", ")")~" funcptr; } }"; //const char[] FancyDelegate = "union "~O.stringof~"Delegate { "~D.stringof~" dg; struct { "~O.stringof~"* ptr; "~D.stringof.replace("delegate(", "function(")~" funcptr; } }"; } class X { public int z = 2; public void foo(int x) { //writeln(this.z*x); writeln(x); } } void delegate(int) dg; mixin(FancyDelegate!(X, typeof(dg))); void main() { auto xX = new X(); XDelegate x; x.dg = &xX.foo; //x.dg(3); x.ptr = &xX; x.funcptr(xX, 5); //x.funcptr(5); getch(); } Unfortunately this fails when entering the function. I've tried various things(passing &xX, etc..., passing nothing(the comments, etc.) I thought a delegate, when called, was called like a member function? It seems that a delegate is some magic black box that we can't emulate in any way shape or form due to the calling conventions used?
Sep 09 2015
08-Jun-2013 03:21, Manu пишет:So from my dconf talk, I detailed a nasty hack to handle member function pointers in D. My approach is not portable, so I'd like to see an expression formalised in D, so this sort of interaction with C++ is possible, and also it may be useful in D code directly. I'm thinking something like this... Keen to hear thoughts. My approach was this: void function(T _this, ...args...); Explicit 'this' pointer; only works with ABI's that pass 'this' as the first integer argument.I decided to see how convenient can be a solution to auto-generate a thunk function that has exactly this signutre. In ABIs where this is passed as first parameters that shouldn't be much of overhead. Here is my first try, it needs to handle overload sets but that could be added. Second point is perfect forwarding (there is forward in std.typecons, avoided for now). It may as well depend on compiler bugs but it looks nice and clean :) module mem_fun; import std.traits, std.stdio; template memThunk(string call, T, U...) if(is(T == class)) { auto memThunk(T self, U args) { return mixin("self." ~ call~"(args)"); } } struct memberFunc(T) if(is(T == class)) { static property auto opDispatch(string fn)() { alias FnType = typeof(mixin("T."~fn)); return &memThunk!(fn, T, ParameterTypeTuple!FnType); } } class A{ void foo(int k) { writefln("Quack %d!\n", k); } } unittest { void function (A, int) fun = memberFunc!A.foo; A a = new A(); fun(a, 45); //prints Quack 45! } P.S. Having a way to express this-call calling convention explicitly could be very useful still especially taking into account recent enhancements to the extern(C++) support. -- Dmitry Olshansky
Jun 10 2013
On Friday, 7 June 2013 at 23:22:03 UTC, Manu wrote:I think this makes good sense, because other than the choice of calling convention, it really is just a 'function' in every other way.Another less intrusive option would be to just add extern(CppThisCall) and extern(DThisCall) or something along the lines, which would be specified to pass the first parameter as if it was a this pointer. David
Jun 10 2013
On 10 June 2013 23:46, David Nadlinger <code klickverbot.at> wrote:On Friday, 7 June 2013 at 23:22:03 UTC, Manu wrote:That would also do the business. Do you think that's less intrusive? It feels a little hacky though. 'DThisCall' isn't really 'extern' so to speak. I like my suggestion a lot more. Little details like, what would you name the 'this' argument? You'll end up with conventions like 'void function(T _this)', and that's a bit untrue because there isn't an argument named '_this', it's called 'this' inside the method.I think this makes good sense, because other than the choice of calling convention, it really is just a 'function' in every other way.Another less intrusive option would be to just add extern(CppThisCall) and extern(DThisCall) or something along the lines, which would be specified to pass the first parameter as if it was a this pointer.
Jun 10 2013
On Monday, 10 June 2013 at 14:04:29 UTC, Manu wrote:On 10 June 2013 23:46, David Nadlinger <code klickverbot.at>Less intrusive in the way that it is a minimal addition to the language itself (we already have several calling conventions), whereas your suggestion would require adding a special case to the grammar. That's not to say I don't like your proposal, though. I just wanted to put the option on the table to be sure we are getting somewhere with this, even if some people might be opposed to the grammar change. This issue has been bugging me for quite some time as well.Another less intrusive option would be to just add extern(CppThisCall) and extern(DThisCall) or something along the lines, which would be specified to pass the first parameter as if it was a this pointer.That would also do the business. Do you think that's less intrusive?It feels a little hacky though. 'DThisCall' isn't really 'extern' so to speak.extern(D) exists today – extern(xyz) should really be called abi(xyz), callingconv(xyz) or something like that instead. David
Jun 10 2013
On 2013-06-10 14:11:31 +0000, "David Nadlinger" <code klickverbot.at> said:On Monday, 10 June 2013 at 14:04:29 UTC, Manu wrote:It's inelegant, but it could work. I just find it sad that we have to use a different calling convention for member functions. I mean, it'd be much more elegant be if a member function could simply be called from a "void function(Object)" by supplying "this" as the first argument? Wouldn't it be better to adapt the ABI to fit the language rather than adapt the language to fit the ABI? -- Michel Fortin michel.fortin michelf.ca http://michelf.ca/On 10 June 2013 23:46, David Nadlinger <code klickverbot.at>Less intrusive in the way that it is a minimal addition to the language itself (we already have several calling conventions), whereas your suggestion would require adding a special case to the grammar. That's not to say I don't like your proposal, though. I just wanted to put the option on the table to be sure we are getting somewhere with this, even if some people might be opposed to the grammar change. This issue has been bugging me for quite some time as well.Another less intrusive option would be to just add extern(CppThisCall) and extern(DThisCall) or something along the lines, which would be specified to pass the first parameter as if it was a this pointer.That would also do the business. Do you think that's less intrusive?
Jun 10 2013
On 11 June 2013 00:28, Michel Fortin <michel.fortin michelf.ca> wrote:On 2013-06-10 14:11:31 +0000, "David Nadlinger" <code klickverbot.at> said: On Monday, 10 June 2013 at 14:04:29 UTC, Manu wrote:The ABI is the better part of half a century old...It's inelegant, but it could work. I just find it sad that we have to use a different calling convention for member functions. I mean, it'd be much more elegant be if a member function could simply be called from a "void function(Object)" by supplying "this" as the first argument? Wouldn't it be better to adapt the ABI to fit the language rather than adapt the language to fit the ABI?On 10 June 2013 23:46, David Nadlinger <code klickverbot.at>Less intrusive in the way that it is a minimal addition to the language itself (we already have several calling conventions), whereas your suggestion would require adding a special case to the grammar. That's not to say I don't like your proposal, though. I just wanted to put the option on the table to be sure we are getting somewhere with this, even if some people might be opposed to the grammar change. This issue has been bugging me for quite some time as well.Another less intrusive option would be to just add extern(CppThisCall) and extern(DThisCall) or something along the lines, which would be specified to pass the first parameter as if it was a this pointer.That would also do the business. Do you think that's less intrusive?
Jun 10 2013
On 6/10/2013 7:33 AM, Manu wrote:[...]Sorry to say, your n.g. poster is back to its old tricks :-)
Sep 09 2015
On Wednesday, 9 September 2015 at 18:55:18 UTC, Walter Bright wrote:On 6/10/2013 7:33 AM, Manu wrote:On 6/10/2013 That was 2 years ago.[...]Sorry to say, your n.g. poster is back to its old tricks :-)
Sep 09 2015
On 9/9/2015 1:17 PM, Freddy wrote:On Wednesday, 9 September 2015 at 18:55:18 UTC, Walter Bright wrote:Woops! I didn't notice. My reader sorts things based on the date of the last post.On 6/10/2013 7:33 AM, Manu wrote:On 6/10/2013 That was 2 years ago.[...]Sorry to say, your n.g. poster is back to its old tricks :-)
Sep 09 2015
On 10 September 2015 at 04:55, Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 6/10/2013 7:33 AM, Manu wrote:We've resolved this issue since 6/10/2013 no? ;)[...]Sorry to say, your n.g. poster is back to its old tricks :-)
Sep 09 2015
On 9/9/2015 6:52 PM, Manu via Digitalmars-d wrote:We've resolved this issue since 6/10/2013 no? ;):-)
Sep 09 2015
On Thursday, 10 September 2015 at 01:52:17 UTC, digitalmars.D wrote:On 10 September 2015 at 04:55, Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:In the web forum, this post shows up as having author "digitalmars.D", not even "Manu via Digitalmars-d" like your posts normally do and definitely not "Manu" like it should. CyberShadow?On 6/10/2013 7:33 AM, Manu wrote:We've resolved this issue since 6/10/2013 no? ;)[...]Sorry to say, your n.g. poster is back to its old tricks :-)
Sep 10 2015
On Thursday, 10 September 2015 at 16:18:13 UTC, John Colvin wrote:On Thursday, 10 September 2015 at 01:52:17 UTC, digitalmars.D wrote:Heh. My fault. Fixed (though it'll stick for that post in some views).On 10 September 2015 at 04:55, Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:In the web forum, this post shows up as having author "digitalmars.D", not even "Manu via Digitalmars-d" like your posts normally do and definitely not "Manu" like it should. CyberShadow?On 6/10/2013 7:33 AM, Manu wrote:We've resolved this issue since 6/10/2013 no? ;)[...]Sorry to say, your n.g. poster is back to its old tricks :-)
Sep 10 2015
On Thursday, 10 September 2015 at 16:24:52 UTC, Vladimir Panteleev wrote:Heh. My fault. Fixed (though it'll stick for that post in some views).Now the main index says: "Unexpected end of input when converting from type string to type long".
Sep 10 2015
On Thursday, 10 September 2015 at 19:40:02 UTC, Ola Fosheim Grøstad wrote:On Thursday, 10 September 2015 at 16:24:52 UTC, Vladimir Panteleev wrote:Doesn't happen here, so that's something local to you, almost surely unrelated to the above. Try clearing your cookies.Heh. My fault. Fixed (though it'll stick for that post in some views).Now the main index says: "Unexpected end of input when converting from type string to type long".
Sep 10 2015
On Thursday, 10 September 2015 at 20:15:15 UTC, Vladimir Panteleev wrote:On Thursday, 10 September 2015 at 19:40:02 UTC, Ola Fosheim Grøstad wrote:Request URL:http://forum.dlang.org/ Request Method:GET Status Code:500 Internal Server ErrorOn Thursday, 10 September 2015 at 16:24:52 UTC, Vladimir Panteleev wrote:Doesn't happen here, so that's something local to you, almost surely unrelated to the above. Try clearing your cookies.Heh. My fault. Fixed (though it'll stick for that post in some views).Now the main index says: "Unexpected end of input when converting from type string to type long".
Sep 10 2015
On Thursday, 10 September 2015 at 21:24:17 UTC, Ola Fosheim Grøstad wrote:On Thursday, 10 September 2015 at 20:15:15 UTC, Vladimir Panteleev wrote:Doesn't happen here, so that's something local to you, almost surely unrelated to the above. Try clearing your cookies.On Thursday, 10 September 2015 at 19:40:02 UTC, Ola Fosheim Grøstad wrote:Request URL:http://forum.dlang.org/ Request Method:GET Status Code:500 Internal Server ErrorOn Thursday, 10 September 2015 at 16:24:52 UTC, Vladimir Panteleev wrote:Doesn't happen here, so that's something local to you, almost surely unrelated to the above. Try clearing your cookies.Heh. My fault. Fixed (though it'll stick for that post in some views).Now the main index says: "Unexpected end of input when converting from type string to type long".
Sep 10 2015
On Thursday, 10 September 2015 at 21:29:15 UTC, Vladimir Panteleev wrote:Doesn't happen here, so that's something local to you, almost surely unrelated to the above. Try clearing your cookies.Yes, it was caused by cookies, but it wasn't local since it returned a HTTP status 500. It happend on the web server.
Sep 10 2015
On Thursday, 10 September 2015 at 16:24:52 UTC, Vladimir Panteleev wrote:... Heh. My fault. Fixed (though it'll stick for that post in some views).Correct a "D-Runtime" topic, please. It is not updated.
Sep 10 2015
On Friday, 11 September 2015 at 00:37:35 UTC, data man wrote:On Thursday, 10 September 2015 at 16:24:52 UTC, Vladimir Panteleev wrote:Not sure what you mean, please clarify. If it's not related to this thread, please file bugs on https://github.com/CyberShadow/DFeed/issues to avoid off-topic discussion.... Heh. My fault. Fixed (though it'll stick for that post in some views).Correct a "D-Runtime" topic, please. It is not updated.
Sep 11 2015
"Michel Fortin" <michel.fortin michelf.ca> wrote in message news:kp4nr0$q71$1 digitalmars.com...I just find it sad that we have to use a different calling convention for member functions. I mean, it'd be much more elegant be if a member function could simply be called from a "void function(Object)" by supplying "this" as the first argument? Wouldn't it be better to adapt the ABI to fit the language rather than adapt the language to fit the ABI?For D, yes, and it would be awesome. For everything else, never ever ever.
Jun 11 2013
On 6/7/2013 4:21 PM, Manu wrote:So from my dconf talk, I detailed a nasty hack to handle member function pointers in D.https://www.digitalmars.com/articles/b68.html
Sep 09 2015
On Wednesday, 9 September 2015 at 18:50:45 UTC, Walter Bright wrote:On 6/7/2013 4:21 PM, Manu wrote:Here's on automatic version import std.traits : Parameters; enum MemberFunc(alias Type, string member) = (ref Type self, Parameters!(__traits(getMember, Type, member)) args) => mixin(q{self.} ~ member ~ q{(args)}); unittest { static struct A { bool test; void b(int arg) { test = arg == 4; } } A a; auto func = MemberFunc!(A, "b"); func(a,4); assert(a.test); }So from my dconf talk, I detailed a nasty hack to handle member function pointers in D.https://www.digitalmars.com/articles/b68.html
Sep 09 2015
On Wednesday, 9 September 2015 at 20:18:06 UTC, Freddy wrote:enum MemberFunc(alias Type, string member) = (ref Type self, Parameters!(__traits(getMember, Type, member)) args) => mixin(q{self.} ~ member ~ q{(args)});Whoops the alias wasn't needed enum MemberFunc(Type, string member) = (ref Type self, Parameters!(__traits(getMember, Type, member)) args) => mixin(q{self.} ~ member ~ q{(args)});
Sep 09 2015