digitalmars.D.learn - Class info on interfaces
- Jacob Carlborg (16/16) Aug 26 2015 I noticed the calling "classinfo" on an interface returns the class info...
- Adam D. Ruppe (8/9) Aug 26 2015 Yes, exactly. COM and C++ things won't necessarily have a D
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (6/12) Aug 26 2015 To complete, the documentation says ".classinfo applied to an interface
- Jacob Carlborg (7/11) Aug 27 2015 Is it possible to detect at compile time if an interface is not a native...
- Adam D. Ruppe (15/19) Aug 28 2015 Not fully, no, but you might be able to reflect into the methods
- Jacob Carlborg (7/13) Aug 28 2015 Well, this would be for my serialization library. If the static type
- rumbu (11/24) Aug 28 2015 I don't know about Objective-C, but:
- Jacob Carlborg (5/13) Aug 28 2015 I'm wondering how reliable that is. Might be better to check the linkage...
- rumbu (40/54) Aug 28 2015 The linkage check it's good as long you don't have an abomination
- Jacob Carlborg (6/41) Aug 29 2015 That looks like a pretty good idea, thanks. I'm wondering if it's worth
I noticed the calling "classinfo" on an interface returns the class info of the static type and not the dynamic type. Is that intentional? Perhaps because of COM and C++ interfaces? module main; import std.stdio; interface Foo {} class Bar : Foo {} void main() { Foo f = new Bar; writeln(f.classinfo); } The above program will print the static type "main.Foo" instead of the dynamic type "main.Bar". -- /Jacob Carlborg
Aug 26 2015
On Wednesday, 26 August 2015 at 18:53:19 UTC, Jacob Carlborg wrote:Is that intentional? Perhaps because of COM and C++ interfaces?Yes, exactly. COM and C++ things won't necessarily have a D TypeInfo available and since interfaces can be them, it can't be sure. What I do there is to just cast the interface to Object. Then you should check for null to cover those cases, then you can typeid or classinfo it.
Aug 26 2015
On 08/26/2015 11:59 AM, Adam D. Ruppe wrote:On Wednesday, 26 August 2015 at 18:53:19 UTC, Jacob Carlborg wrote:To complete, the documentation says ".classinfo applied to an interface gives the information for the interface, not the class it might be an instance of." http://dlang.org/property.html#classinfo AliIs that intentional? Perhaps because of COM and C++ interfaces?Yes, exactly. COM and C++ things won't necessarily have a D TypeInfo available and since interfaces can be them, it can't be sure. What I do there is to just cast the interface to Object. Then you should check for null to cover those cases, then you can typeid or classinfo it.
Aug 26 2015
On 2015-08-26 20:59, Adam D. Ruppe wrote:Yes, exactly. COM and C++ things won't necessarily have a D TypeInfo available and since interfaces can be them, it can't be sure. What I do there is to just cast the interface to Object. Then you should check for null to cover those cases, then you can typeid or classinfo it.Is it possible to detect at compile time if an interface is not a native D interface? Now when I think about it, we actually have four (!) different kinds of interfaces. Native D, C++, Objective-C and COM. -- /Jacob Carlborg
Aug 27 2015
On Friday, 28 August 2015 at 06:19:55 UTC, Jacob Carlborg wrote:Is it possible to detect at compile time if an interface is not a native D interface?Not fully, no, but you might be able to reflect into the methods and see what kind of linkage they have. http://dlang.org/phobos/std_traits.html#functionLinkage The interface itself won't necessarily be marked extern - on the binary level, they are all the same (I think... just a pointer to a list of function pointers), but if you look at the methods you can make a reasonably good guess. However, you can't do anything with an interface that isn't in there anyway without a runtime cast, so you might want to just skip any compile time guesses and just go with the runtime check.Now when I think about it, we actually have four (!) different kinds of interfaces. Native D, C++, Objective-C and COM.aye, and since the interface is so simple at the binary level, it is possible to use them for other things too (I think a glib object in C is also binary compatible...); I'm sure this won't be the end of the list.
Aug 28 2015
On 2015-08-28 16:31, Adam D. Ruppe wrote:Not fully, no, but you might be able to reflect into the methods and see what kind of linkage they have. http://dlang.org/phobos/std_traits.html#functionLinkageThat might work.However, you can't do anything with an interface that isn't in there anyway without a runtime cast, so you might want to just skip any compile time guesses and just go with the runtime check.Well, this would be for my serialization library. If the static type it's not a native D interface I don't have way to recreate the instance when deserializing, at least not with the default deserialization process. -- /Jacob Carlborg
Aug 28 2015
On Friday, 28 August 2015 at 06:19:55 UTC, Jacob Carlborg wrote:On 2015-08-26 20:59, Adam D. Ruppe wrote:I don't know about Objective-C, but: - for native D interfaces __traits(getVirtualIndex, NativeInterface.firstFunction) == 1 since the first entry in vtbl is the contained object - for C++ interfaces __traits(getVirtualIndex, CPPInterface.firstFunction) == 0 - COM interfaces: __traits(getVirtualIndex, CPPInterface.firstFunction) == 0 and inherit IUnknown At runtime, it's simple, you have the m_flags member of TypeInfo_Class (isCPPclass, isCOMclass)Yes, exactly. COM and C++ things won't necessarily have a D TypeInfo available and since interfaces can be them, it can't be sure. What I do there is to just cast the interface to Object. Then you should check for null to cover those cases, then you can typeid or classinfo it.Is it possible to detect at compile time if an interface is not a native D interface? Now when I think about it, we actually have four (!) different kinds of interfaces. Native D, C++, Objective-C and COM.
Aug 28 2015
On 2015-08-28 17:41, rumbu wrote:I don't know about Objective-C, but: - for native D interfaces __traits(getVirtualIndex, NativeInterface.firstFunction) == 1 since the first entry in vtbl is the contained object - for C++ interfaces __traits(getVirtualIndex, CPPInterface.firstFunction) == 0 - COM interfaces: __traits(getVirtualIndex, CPPInterface.firstFunction) == 0 and inherit IUnknownI'm wondering how reliable that is. Might be better to check the linkage of a method in the interface as Adam suggested. -- /Jacob Carlborg
Aug 28 2015
On Friday, 28 August 2015 at 19:36:37 UTC, Jacob Carlborg wrote:On 2015-08-28 17:41, rumbu wrote:The linkage check it's good as long you don't have an abomination like this: extern(C++) interface CPPInterface { extern(D) void foo(); } Anyway, the problem is the availability of such function. If the interface doesn't contain any function, there is no way to detect the type, except for COM Interfaces which are clearly implementing IUnknown. But deriving a new interface and defining a sentinel function, it works: import std.stdio; import std.traits; import core.sys.windows.com; interface NativeInterface {} interface COMInterface : IUnknown {} extern(C++) interface CPPInterface {} enum InterfaceKind { native, windows, cpp } template interfaceKind(I) if (is(I == interface)) { interface J : I { void __foo__(); } static if (functionLinkage!(J.__foo__) == "D") enum interfaceKind = InterfaceKind.native; else static if (functionLinkage!(J.__foo__) == "Windows") enum interfaceKind = InterfaceKind.windows; else static if (functionLinkage!(J.__foo__) == "C++") enum interfaceKind = InterfaceKind.cpp; else static assert(false, "Unknown interface kind."); } int main(string[] argv) { static assert(interfaceKind!NativeInterface == InterfaceKind.native); static assert(interfaceKind!COMInterface == InterfaceKind.windows); static assert(interfaceKind!CPPInterface == InterfaceKind.cpp); return 0; }I don't know about Objective-C, but: - for native D interfaces __traits(getVirtualIndex, NativeInterface.firstFunction) == 1 since the first entry in vtbl is the contained object - for C++ interfaces __traits(getVirtualIndex, CPPInterface.firstFunction) == 0 - COM interfaces: __traits(getVirtualIndex, CPPInterface.firstFunction) == 0 and inherit IUnknownI'm wondering how reliable that is. Might be better to check the linkage of a method in the interface as Adam suggested.
Aug 28 2015
On 2015-08-28 22:40, rumbu wrote:The linkage check it's good as long you don't have an abomination like this: extern(C++) interface CPPInterface { extern(D) void foo(); }Good point.Anyway, the problem is the availability of such function. If the interface doesn't contain any function, there is no way to detect the type, except for COM Interfaces which are clearly implementing IUnknown. But deriving a new interface and defining a sentinel function, it works: import std.stdio; import std.traits; import core.sys.windows.com; interface NativeInterface {} interface COMInterface : IUnknown {} extern(C++) interface CPPInterface {} enum InterfaceKind { native, windows, cpp } template interfaceKind(I) if (is(I == interface)) { interface J : I { void __foo__(); } static if (functionLinkage!(J.__foo__) == "D") enum interfaceKind = InterfaceKind.native; else static if (functionLinkage!(J.__foo__) == "Windows") enum interfaceKind = InterfaceKind.windows; else static if (functionLinkage!(J.__foo__) == "C++") enum interfaceKind = InterfaceKind.cpp; else static assert(false, "Unknown interface kind."); } int main(string[] argv) { static assert(interfaceKind!NativeInterface == InterfaceKind.native); static assert(interfaceKind!COMInterface == InterfaceKind.windows); static assert(interfaceKind!CPPInterface == InterfaceKind.cpp); return 0; }That looks like a pretty good idea, thanks. I'm wondering if it's worth implementing a trait for this in the compiler. -- /Jacob Carlborg
Aug 29 2015