D - vtable
- Pavel Minayev (12/12) Jan 18 2002 I wonder if I can rely on the order of methods in vtable
- Pavel Minayev (3/3) Jan 18 2002 Also, does the same apply to interfaces (it should, IMO, since
- Walter (5/8) Jan 18 2002 I doubt the order will be anything but declaration order.
- Pavel Minayev (8/9) Jan 18 2002 In _both_ cases (the first would be better!).
- Pavel Minayev (4/5) Jan 18 2002 Sorry forgot to put the ? at the end =)
- Walter (4/9) Jan 18 2002 Yes, in both cases it is true. And yes, I intend for the ClassInfo to be
- OddesE (7/15) Jan 18 2002 found
- Pavel Minayev (8/12) Jan 18 2002 components
- OddesE (12/24) Jan 18 2002 No problem, just hadn't thought of that. However, since COM interfaces:
- Pavel Minayev (10/13) Jan 18 2002 Maybe because they store ClassInfo?
- OddesE (13/26) Jan 18 2002 that
- Pavel Minayev (5/9) Jan 18 2002 Some special language construct?
- Juan Carlos Arevalo Baeza (8/21) Jan 18 2002 that
- Walter (23/27) Jan 18 2002 components
- Pavel Minayev (12/26) Jan 18 2002 Why (3)? Isn't extern(Windows) applicable to methods? I remember
- Walter (5/31) Jan 18 2002 Yes, the extern works with methods. It just isn't the default.
- Russell Borogove (4/8) Jan 18 2002 Actually, from the outside it sounds pretty elegant, even if
- OddesE (16/24) Jan 19 2002 called
- Roland (7/19) Jan 18 2002 At last you got it (vtbl) ?
- Pavel Minayev (9/12) Jan 18 2002 ? It always was there!
- roland (9/16) Jan 18 2002 ? don't see in the spec.
- Pavel Minayev (44/51) Jan 18 2002 The best spec is Phobos source, see the files object.d and
- Pavel Minayev (24/29) Jan 18 2002 An idea came to my mind... what if compiler generates an enum for each
- Walter (4/34) Jan 18 2002 just
- Pavel Minayev (12/13) Jan 18 2002 Overloaded ones could be skipped:
- Pavel Minayev (11/11) Jan 18 2002 Or even:
- Patrick Down (15/26) Jan 18 2002 I suppose this would be rather iky?
- Pavel Minayev (11/22) Jan 19 2002 Yep, because imagine a user trying to build the name
- Walter (3/4) Jan 20 2002 No, for the same reasons as in C++. It prevents bottom up semantic analy...
- Pavel Minayev (8/8) Jan 19 2002 Okay, so it turned out to be not that simple...
- Pavel Minayev (25/25) Jan 19 2002 I should have thought twice before posting... =)
- Walter (3/5) Jan 20 2002 I thought that worked. If not, it's a bug. -Walter
I wonder if I can rely on the order of methods in vtable being the same as order of their declaration? class Something { void qwerty(); void asdf(); } Something thing; ... thing.classinfo.vtbl[thing.classinfo.vtbl.length - 1]; // asdf()? thing.classinfo.vtbl[thing.classinfo.vtbl.length - 2]; // qwerty()? It seems to work with DMD, but is it portable?
Jan 18 2002
Also, does the same apply to interfaces (it should, IMO, since interfaces sometimes just ought to have fixed, predefined order of methods - if used with COM, for example....)
Jan 18 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:a29jef$1d1a$1 digitaldaemon.com...Also, does the same apply to interfaces (it should, IMO, since interfaces sometimes just ought to have fixed, predefined order of methods - if used with COM, for example....)I doubt the order will be anything but declaration order. (COM won't work with interfaces, for some obscure technical reasons. I found another way to do it.)
Jan 18 2002
"Walter" <walter digitalmars.com> wrote in message news:a29vu9$2ppj$1 digitaldaemon.com...I doubt the order will be anything but declaration order.In _both_ cases (the first would be better!). I'm still searching for the solution of method pointers - well you've probably guessed =) - so now it seems I've found it. BTW is the ClassInfo stuff implementation-dependent or it is supposed to be strictly defined? In other words, can I rely on the fact that on any platform ClassInfo contains void*[] vtbl?
Jan 18 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:a2a4os$2sr5$1 digitaldaemon.com...In _both_ cases (the first would be better!).Sorry forgot to put the ? at the end =) So, in both cases?
Jan 18 2002
Yes, in both cases it is true. And yes, I intend for the ClassInfo to be cast in concrete, however, new members may get appended. "Pavel Minayev" <evilone omen.ru> wrote in message news:a2a5cs$2t7r$1 digitaldaemon.com..."Pavel Minayev" <evilone omen.ru> wrote in message news:a2a4os$2sr5$1 digitaldaemon.com...In _both_ cases (the first would be better!).Sorry forgot to put the ? at the end =) So, in both cases?
Jan 18 2002
"Walter" <walter digitalmars.com> wrote in message news:a29vu9$2ppj$1 digitaldaemon.com..."Pavel Minayev" <evilone omen.ru> wrote in message news:a29jef$1d1a$1 digitaldaemon.com...foundAlso, does the same apply to interfaces (it should, IMO, since interfaces sometimes just ought to have fixed, predefined order of methods - if used with COM, for example....)I doubt the order will be anything but declaration order. (COM won't work with interfaces, for some obscure technical reasons. Ianother way to do it.)Yes, I meant to ask that? Is it possible to work with / write COM components in D? How does it work? You would think interfaces would be perfectly suited to COM?
Jan 18 2002
"OddesE" <OddesE_XYZ hotmail.com> wrote in message news:a2a5gd$2th1$1 digitaldaemon.com...Yes, I meant to ask that? Is it possible to work with / write COMcomponentsin D? How does it work? You would think interfaces would be perfectly suited to COM?Other than the inability to produce DLLs (or am I wrong?), I don't really see any problems in writing a COM component. Interfaces won't suite, as Walter has just told us =), but you can always use structures. Function pointers are there as well, so what's the problem?
Jan 18 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:a2a5on$2tj1$1 digitaldaemon.com..."OddesE" <OddesE_XYZ hotmail.com> wrote in message news:a2a5gd$2th1$1 digitaldaemon.com...No problem, just hadn't thought of that. However, since COM interfaces: have exactly the same functionality as D interfaces you would expect that you would be able to use them. I am just wondering why you can't, it is not like I am not believing Walter or anything.... :) -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net __________________________________________ Remove _XYZ from my address when replying by mailYes, I meant to ask that? Is it possible to work with / write COMcomponentsin D? How does it work? You would think interfaces would be perfectly suited to COM?Other than the inability to produce DLLs (or am I wrong?), I don't really see any problems in writing a COM component. Interfaces won't suite, as Walter has just told us =), but you can always use structures. Function pointers are there as well, so what's the problem?
Jan 18 2002
"OddesE" <OddesE_XYZ hotmail.com> wrote in message news:a2a6jl$2u00$1 digitaldaemon.com...have exactly the same functionality as D interfaces you would expect that you would be able to use them. I am just wondering why you can't, it is not like I am not believing Walter or anything.... :)Maybe because they store ClassInfo? // object.d struct Interface { ClassInfo classinfo; void *[] vtbl; } Just a thought...
Jan 18 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:a2a9r5$3077$1 digitaldaemon.com..."OddesE" <OddesE_XYZ hotmail.com> wrote in message news:a2a6jl$2u00$1 digitaldaemon.com...thathave exactly the same functionality as D interfaces you would expectSeems logical...But maybe it could be tweaked around to be compatible with COM? That would be more natural than using structs with tables of function pointers IMHO... -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net __________________________________________ Remove _XYZ from my address when replying by mailyou would be able to use them. I am just wondering why you can't, it is not like I am not believing Walter or anything.... :)Maybe because they store ClassInfo? // object.d struct Interface { ClassInfo classinfo; void *[] vtbl; } Just a thought...
Jan 18 2002
"OddesE" <OddesE_XYZ hotmail.com> wrote in message news:a2acsb$mj$1 digitaldaemon.com...Seems logical...But maybe it could be tweaked around to be compatible with COM? That would be more natural than using structs with tables of function pointers IMHO...Some special language construct? BTW also because vtbl is a dynamic array, so it's practically a struct { pointer, int }...
Jan 18 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:a2a9r5$3077$1 digitaldaemon.com..."OddesE" <OddesE_XYZ hotmail.com> wrote in message news:a2a6jl$2u00$1 digitaldaemon.com...thathave exactly the same functionality as D interfaces you would expectClassInfo pointers can (and should? I don't know the internals of D that well... but C++ does it that way) be stored in the vtbl (as the [-1] pointer) and stay COM-compatible. Salutaciones, JCAByou would be able to use them. I am just wondering why you can't, it is not like I am not believing Walter or anything.... :)Maybe because they store ClassInfo? // object.d struct Interface { ClassInfo classinfo; void *[] vtbl; } Just a thought...
Jan 18 2002
"OddesE" <OddesE_XYZ hotmail.com> wrote in message news:a2a5gd$2th1$1 digitaldaemon.com...Yes, I meant to ask that? Is it possible to work with / write COMcomponentsin D? How does it work? You would think interfaces would be perfectly suited to COM?COM requires: 1) the first entry in an object is a vptr 2) the layout of the vtbl[] is exactly like C++ single inheritance 3) stdcall calling conventions 4) AddRef() and Release() memory management. D Objects fail (2), (3), (4) [(2) because the first entry in the vtbl[] is the ClassInfo followed by the Object functions]. D Interfaces fail (1), (3), (4). The solution is to recognize a special root object (strangely enough called "IUnknown" <g>). Deriving from this, instead of from Object, means you wind up with a COM style vtbl[], and it also sets the function calling conventions to stdcall. This has some effects like you can't do a .classinfo on a COM object (no rtti). COM objects are also reference counted, and are not on the garbage collected heap. It sounds wartier than it actually is. In my experiments, it's much more natural to write COM code in D than it is in C++, despite COM being designed for C++. Portability of this kludge is not an issue, since COM is only for Windows anyway. It will be possible to write DLLs in D, I just haven't written the necessary library support for it yet.
Jan 18 2002
"Walter" <walter digitalmars.com> wrote in message news:a2ad4l$128$1 digitaldaemon.com...COM requires: 1) the first entry in an object is a vptr 2) the layout of the vtbl[] is exactly like C++ single inheritance 3) stdcall calling conventions 4) AddRef() and Release() memory management.D Interfaces fail (1), (3), (4).Why (3)? Isn't extern(Windows) applicable to methods? I remember you used extern(C) for OutBuffer.printf() (and so did I for Stream.printf(), then =)), and it worked...The solution is to recognize a special root object (strangely enoughcalled"IUnknown" <g>). Deriving from this, instead of from Object, means youwindup with a COM style vtbl[], and it also sets the function calling conventions to stdcall. This has some effects like you can't do a.classinfoon a COM object (no rtti). COM objects are also reference counted, and are not on the garbage collected heap.It's pretty okay.It will be possible to write DLLs in D, I just haven't written thenecessarylibrary support for it yet....which is pretty possible to do ourselves, right? Isn't is as simple as providing our own version of dmain2.d?
Jan 18 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:a2aes3$24o$1 digitaldaemon.com..."Walter" <walter digitalmars.com> wrote in message news:a2ad4l$128$1 digitaldaemon.com...Yes, the extern works with methods. It just isn't the default.COM requires: 1) the first entry in an object is a vptr 2) the layout of the vtbl[] is exactly like C++ single inheritance 3) stdcall calling conventions 4) AddRef() and Release() memory management.D Interfaces fail (1), (3), (4).Why (3)? Isn't extern(Windows) applicable to methods? I remember you used extern(C) for OutBuffer.printf() (and so did I for Stream.printf(), then =)), and it worked...areThe solution is to recognize a special root object (strangely enoughcalled"IUnknown" <g>). Deriving from this, instead of from Object, means youwindup with a COM style vtbl[], and it also sets the function calling conventions to stdcall. This has some effects like you can't do a.classinfoon a COM object (no rtti). COM objects are also reference counted, andYeah, that's about it.not on the garbage collected heap.It's pretty okay.It will be possible to write DLLs in D, I just haven't written thenecessarylibrary support for it yet....which is pretty possible to do ourselves, right? Isn't is as simple as providing our own version of dmain2.d?
Jan 18 2002
Walter wrote:The solution is to recognize a special root object (strangely enough called "IUnknown" <g>). [details omitted] It sounds wartier than it actually is.Actually, from the outside it sounds pretty elegant, even if it's warty on the inside. -RB
Jan 18 2002
"Russell Borogove" <kaleja estarcion.com> wrote in message news:3C48E52C.10801 estarcion.com...Walter wrote:calledThe solution is to recognize a special root object (strangely enoughIndeed, it does sound pretty elegant! Is the IUnknown root object part of the standard D libraries? Très Cool! I was delving into COM just before I learned of D, and I like both of them a lot, but I had I concern I couldn't mix coding with the two, so that would have been a shame. It is great to hear that not only is it supported, but that it is actually cleaner to do than in C++! -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net __________________________________________ Remove _XYZ from my address when replying by mail"IUnknown" <g>). [details omitted] It sounds wartier than it actually is.Actually, from the outside it sounds pretty elegant, even if it's warty on the inside. -RB
Jan 19 2002
Pavel Minayev a écrit :I wonder if I can rely on the order of methods in vtable being the same as order of their declaration? class Something { void qwerty(); void asdf(); } Something thing; ... thing.classinfo.vtbl[thing.classinfo.vtbl.length - 1]; // asdf()? thing.classinfo.vtbl[thing.classinfo.vtbl.length - 2]; // qwerty()? It seems to work with DMD, but is it portable?At last you got it (vtbl) ? For portability and readeability it would be nice something like thing.classinfo.vtbl.qwerty (why do i always have ideas for _more_ work for walter and never for _less_ ?) Roland
Jan 18 2002
"Roland" <rv ronetech.com> wrote in message news:3C486B82.F2E11B62 ronetech.com...At last you got it (vtbl) ?? It always was there!For portability and readeability it would be nice something like thing.classinfo.vtbl.qwertyWhy if you can write "thing.qwerty" ? =) One great thing would be an associative-array vtable (and one for properties as well, storing their offsets from "this"): thing.classinfo.method["qwerty"]; thing.classinfo.property["asdf"];
Jan 18 2002
Pavel Minayev a écrit :"Roland" <rv ronetech.com> wrote in message news:3C486B82.F2E11B62 ronetech.com...? don't see in the spec. vtbl propertie is the virtual table right ? For a little while, I suspect you to make some kind of pointer to methode replacement writing in the vtbl. good idea..At last you got it (vtbl) ?? It always was there!I agree, can you now ? If yes, i missed the conclusion of a previous discussion. RolandFor portability and readeability it would be nice something like thing.classinfo.vtbl.qwertyWhy if you can write "thing.qwerty" ? =)
Jan 18 2002
"roland" <nancyetroland free.fr> wrote in message news:3C489394.B3380956 free.fr...? don't see in the spec.The best spec is Phobos source, see the files object.d and cast.d, how it is used here. Also new.cpp contains code that shows how to create an instance of object by its ClassInfo, bypassing operator new; unfortunately, constructor is not called...vtbl propertie is the virtual table right ?Right. Here's the whole thingie: class ClassInfo : Object { byte[] init; // class static initializer char[] name; // class name void *[] vtbl; // virtual function pointer table Interface[] interfaces; ClassInfo base; void *destructor; void (*_invariant)(Object); } Quite interesting...For a little while, I suspect you to make some kind of pointer to methode replacement writing in the vtbl. good idea..Yes. If order of methods in vtbl is as they're declared, we can always get the address of last method, one before the last, etc. So: class MyForm { this() { // offset from end of vtable is used as function pointer cmdOk.OnClick = Handler.cmdOk_Click; cmdCancel.OnClick = Handler.cmdCancel_Click; } // various methods ... void cmdOk_Click() { ... } void cmdCancel_Click() { ... } // reversed order (count from end) enum Handler { cmdCancel_Click, cmdOk_Click } }You mean to get an address of method? No, I asked Walter about that already: "For an answer right now, it'll be "no". Doesn't mean it will always be that way, doesn't mean that method pointers are a bad idea, I just am buried with work and I can't address it now." Funny, you can write something like &qwerty, which gets parsed fine but causes the compiler to crash later =)Why if you can write "thing.qwerty" ? =)I agree, can you now ?
Jan 18 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:a2a56s$2t6t$1 digitaldaemon.com...You mean to get an address of method? No, I asked Walter about that already: "For an answer right now, it'll be "no". Doesn't mean it will always be that way, doesn't mean that method pointers are a bad idea, I just am buried with work and I can't address it now."An idea came to my mind... what if compiler generates an enum for each class, listing all methods introduced in this class (not overridden!), like this: class Foo { // this is what we type void bar(); int baz(); // and this is what the compiler adds implicitly enum vtable { bar, baz } } Now we have relative positions of methods in vtable. Using classinfo.vtbl and classinfo.base.vtbl, these can easily be converted to pointers: bar_ptr = classinfo.vtbl[classinfo.base.vtbl.length + vtable.bar]; What's also great is that no syntax additions or changes are required, code that would be used to implement this solution is minimal... still all benefits of method pointers are there. What do you think about this, Walter?
Jan 18 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:a2aaa5$30k9$1 digitaldaemon.com..."Pavel Minayev" <evilone omen.ru> wrote in message news:a2a56s$2t6t$1 digitaldaemon.com...justYou mean to get an address of method? No, I asked Walter about that already: "For an answer right now, it'll be "no". Doesn't mean it will always be that way, doesn't mean that method pointers are a bad idea, IIt's a great idea, but doesn't work if functions are overloaded. -Walteram buried with work and I can't address it now."An idea came to my mind... what if compiler generates an enum for each class, listing all methods introduced in this class (not overridden!), like this: class Foo { // this is what we type void bar(); int baz(); // and this is what the compiler adds implicitly enum vtable { bar, baz } } Now we have relative positions of methods in vtable. Using classinfo.vtbl and classinfo.base.vtbl, these can easily be converted to pointers: bar_ptr = classinfo.vtbl[classinfo.base.vtbl.length + vtable.bar]; What's also great is that no syntax additions or changes are required, code that would be used to implement this solution is minimal... still all benefits of method pointers are there. What do you think about this, Walter?
Jan 18 2002
"Walter" <walter digitalmars.com> wrote in message news:a2ad7v$12e$1 digitaldaemon.com...It's a great idea, but doesn't work if functions are overloaded. -WalterOverloaded ones could be skipped: enum vtable { foo, // foo bar = foo + 2, // bar, // bar, baz = bar + 3, }
Jan 18 2002
Or even: enum vtable { foo, // bar, // bar, // bar, baz = foo + 4 } So no pointers for overloaded functions. Who needs them anyhow? =)
Jan 18 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:a2aik2$4l7$1 digitaldaemon.com...Or even: enum vtable { foo, // bar, // bar, // bar, baz = foo + 4 } So no pointers for overloaded functions. Who needs them anyhow? =)I suppose this would be rather iky? enum vtable { foo_v, bar_i, bar_icda, bar_f, baz } // i = int, c = char, da = dynamic array, f = float or better yet thing.classinfo.method{"int bar(int)"]; thing.classinfo.method{"int bar(char[])"]; Walter, are functions in D overloadable on return type?
Jan 18 2002
"Patrick Down" <pdown austin.rr.com> wrote in message news:a2b3lv$f6a$1 digitaldaemon.com...I suppose this would be rather iky? enum vtable { foo_v, bar_i, bar_icda, bar_f, baz } // i = int, c = char, da = dynamic array, f = floatYep, because imagine a user trying to build the name of the function out of its arguments (because he doesn't see that compiler-generated enum). I must say that, having worked with Delphi for a long time, I don't remember any program that took a function pointer to an overloaded function. This is something that can be sacrificed, IMO.thing.classinfo.method{"int bar(int)"]; thing.classinfo.method{"int bar(char[])"];This moves most of the code to run-time (since with enum we already have positions in vtable, and here it has to find a key in an associative array).
Jan 19 2002
"Patrick Down" <pdown austin.rr.com> wrote in message news:a2b3lv$f6a$1 digitaldaemon.com...Walter, are functions in D overloadable on return type?No, for the same reasons as in C++. It prevents bottom up semantic analysis.
Jan 20 2002
Okay, so it turned out to be not that simple... Since extern(D) - the default - doesn't specify order of arguments strictly, it cannot be used in low-level, so methods we want to get pointers to have to be extern(C). The problem is, such methods don't reside in the vtable - they are called directly! So, once again, the only way to get a pointer to it is some special operator, or something...
Jan 19 2002
I should have thought twice before posting... =) Now, I came to the working solution, which seems perferctly portable. The idea is to define a base class for all classes that want pointers to their functions (most frequently it's class itself who uses pointers to its methods anyhow), and let it contain a dummy entry in the vtable - just an empty function - which then gets substituted by whatever pointer we have. So: class Component: Object { // should be the very first void _event_callback(void* ptr) { } } Component obj; ... // put pointer to our callback method into the vtable... obj.classinfo.vtable[Object.classinfo.vtable.length] = our_function_pointer; // ...and call it! obj._event_callback(pointer_to_some_data); Unfortunately D doesn't allow class.classinfo (only object.classinfo) - btw a feature request, Walter! =) - but nothing stops us from creating a temporary Object in static constructor and getting it's vtable.length... So if we get the method-list enumeration, method pointers can be considered there.
Jan 19 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:a2bp3d$vrt$1 digitaldaemon.com...Unfortunately D doesn't allow class.classinfo (only object.classinfo) - btw a feature request, Walter! =)I thought that worked. If not, it's a bug. -Walter
Jan 20 2002