Got an interface puzzle:

Got an interface puzzle:

http://stackoverflow.com/questions/22840183/obtaining-a-sub-interface-from-an-interface

Note that I have plenty of bloated and inefficient solutions to the problem, so really I'm looking for a non-bloat one :-)
http://stackoverflow.com/questions/22840183/obtaining-a-sub-interface-from-an-interface

Comments

  1. Immediately I can't see how given that you've thrown away that information, and that the instance backing the interfaces is the same in either case.

    But then again, I have a limited imagination so I'll be prepared to be amazed :)

    Given your limitation on new instances I presume you want to avoid memory allocations?

    ReplyDelete
  2. The problem is the ISpecialXxx, which is required for the multiple interfaces per instances thing, which does have the ISub in its "inheritence" but doesn't have it explicitly. When using a separate instance per interface, you can use ISub, and then QueryInterface() allows you to recover ISub from the IBase

    ReplyDelete
  3. Hmm it does seem you're not throwing everything away... the pointer returned is different depending on which interface it actually returns. Perhaps you can do some funk with that...

    ReplyDelete
  4. As far as I can see you're still throwing away too much info. I presume letting the interfaces have RTTI info is "bloated" as well?

    ReplyDelete
  5. I don't understand why you cannot list ISub in your class. Is there any reason? Or is it just because you don't write any more of the interface method resolution lines?

    Also as Rob already commented on SO you can still QueryInterface/Supports on ISpecialSub which implicitly also returns ISub.

    ReplyDelete
  6. Because there is a different ISub method set per ISpecial, if you list it at the class, you'll get the same for all.

    ReplyDelete
  7. And how do you think it should return an ISub from an IBase if everything points to the same instance? That would not even work with the GetSub method. Which implementation of the ISub methods should that have? ISpecialSub1, ISpecialSub2 or ISpecialSub3? I am afraid this is not possible except you directly ask for an ISpecialSub and then put that into an ISub reference.

    Your GetTheRightOne method checks a state and then returns an interface depending on that but the state then is lost because you just get an interface to this one and only instance so you cannot ask for anything depending on that state after you returned from that method.

    ReplyDelete
  8. GetTheRightOne actually returns a different pointer for each ISpecial, which isn't lost by the IBase cast, so the information is still there. I've got a hacky solution based on registration of those pointers. If there was a way to "extend" back the pointer it would work in a perhaps less hacky way.

    ReplyDelete
  9. Eric Grange Can this "IsISub" function access the class?

    ReplyDelete
  10. Eric Grange You can have different ISub method implementations using the method resolution clause: http://docwiki.embarcadero.com/RADStudio/XE5/en/Implementing_Interfaces#Method_Resolution_Clause

    ReplyDelete
  11. Asbjørn Heid the ISpecial (and their own ISub) do access the class for settings and parameters (but not for states)

    Ondrej Kelle Method resolution clause is already used in the code, to specify the ISpecial's ISub methods. The problem is going back to the ISub from the ISpecial cast to an IBase

    ReplyDelete
  12. Is there any RTTI generated for interfaces?

    ReplyDelete
  13. Lars Fosdal yes, there is an IntfParent there which holds the information, however you have to start from the child interface, so something might be hackable from the interfaces registered in RTTI, rather than having to manually enumerate them.

    For now I've got another solution that involves creating small classes, but only once per ISpecial, then referencing them in the main class. However when they need to access info from the main class, there is a bit of circular referencing going on, which I'm currently avoiding by overriding the reference count methods so that everything is ref-counted at the main class level.

    ReplyDelete
  14. I got something but it's hackish.

    It parses the VTable info from the interface to determine if the Bar method does not exist in the VTable. If it doesn't it's an IBase, if it does it assumes it's an ISub, in which case a typecast is safe.

    http://pastebin.com/jwqefJPB

    If you got two different ISub's it won't work, as it won't be able to differentiate. I suppose one could extend but that's getting well frisky.

    ReplyDelete

Post a Comment