#29 Support for IDispatch GetTypeInfo

open
nobody
None
4
2015-03-10
2007-09-21
Jason Smith
No

I have been working for Jacob for some time in Java, and I am currently working on some exploratory Groovy/Scriptom improvements. One of the major weaknesses I have noticed is the lack of type information. It would be much easier to write specific wrappers for COM objects if I could determine the type of object at runtime and apply the wrapper (or wrappers) via lookup.

I believe this would open up a whole new world of possibilities with the Groovy/Scriptom implementation, allowing Groovy-specific support for COM-based collections, extension methods/closures, and various syntactical sugar that I don't think is doable without type info.

Thanks!

Discussion

  • clay_shooter

    clay_shooter - 2007-09-27

    Logged In: YES
    user_id=1189284
    Originator: NO

    I'm not sure I understand what you mean. Are you talking about the type of thing that jacobgen does when it creates java classes as wrappers around COM objects. It does this in an incomplete way that is a couple versions behind Jacob.

     
  • Jason Smith

    Jason Smith - 2007-09-27

    Logged In: YES
    user_id=1895760
    Originator: YES

    I don't want to generate static wrappers. Groovy is very dynamic, so it is an excellent fit for Jacob, which is also dynamic at its core.

    I would like *runtime* type information so that I can apply a custom wrapper when it is appropriate to do so, dynamically. I want to use the dynamic nature of Jacob where possible, but I'd like to be able to extend the COM API. Example:

    This is a pseudofunction that runs against an Excel Range object in a hand-coded wrapper that I wrote:

    public boolean getIgnoreError(XlErrorIndex errorIndex)
    {
    ActiveXComponent errors = range.getPropertyAsComponent("Errors");
    ActiveXComponent error = errors.invokeGetComponent("Item", new Variant(errorIndex.intValue()));
    return error.getPropertyAsBoolean("Ignore");
    }

    With Groovy, there is an ActiveXProxy that wraps ActiveXComponent and dynamically translates all method and proerty calls to JACOB calls:

    Another Example:

    import org.codehaus.groovy.scriptom.ActiveXProxy;
    import com.jacob.com.ComThread;

    ComThread.InitSTA();
    try
    {
    def voice = new ActiveXProxy('SAPI.SpVoice')
    voice.Speak 'Hello, you great big GROOVY world!'
    }
    finally
    {
    ComThread.Release();
    }

    Notice how much this looks like VB (VBScript) code? :-) Except for the thread management stuff. You should see what I have done to SafeArrays!

    Anyway...

    What I would like to be able to do is this. Whenever you make a call to a COM component that returns an Excel.Range object, I'd like my code to be able to determine, at runtime, that it is an Excel.Range object. I would then check a list of registered types, that I will maintain, pull out the subclass of ActiveXProxy for Range (call it XLRangeProxy), and wrap the JACOB ActiveXComponent with XLRangeProxy.

    In other words, this would allow me to selectively extend a COM interface without having to wrap every method and property.

    And I am making the assumption that GetTypeInfo is the way to get there, but I could be wrong. :-)

     
  • Jason Smith

    Jason Smith - 2007-09-30

    Logged In: YES
    user_id=1895760
    Originator: YES

    A much simpler use-case, and also a very compelling one, is to be able to get the 'type-name' of the Dispatch at runtime. Right now, a Dispatch is a Dispatch is a Dispatch. It is hard to look up documentation when you don't know the name of the class you are working with. :-) Debugging is important.

     
  • Jason Smith

    Jason Smith - 2007-10-03

    Logged In: YES
    user_id=1895760
    Originator: YES

    Another use case. In Excel, there is a Sheets collection. It returns both Chart and Sheet instances. The only way I have found to reliably tell the difference is to run queryInterface on the object. If I try to queryInterface for a Chart and it is actually a Sheet, it throws an exception. And vice versa.

    It would be much cleaner, and faster, if I didn't have to do this with exception handling. I'd like to be able to just check the type information and wrap it with Sheet.java or Chart.java, which are hand-coded wrappers.

     
  • Jason Smith

    Jason Smith - 2007-10-06

    Logged In: YES
    user_id=1895760
    Originator: YES

    I found a workaround that works for most of what I need. I'm using tlbinf32.dll to pull constants out of type libraries, so it was just an incremental step to enumerate the interfaces and associated GUIDs.

    By trying each GUID in dispatch.QueryInterface() and catching the exception, I can see if the object supports the interface or not. I can only enumerate the interfaces in a particular typelib, not all interfaces, but that doesn't seem to be much of a limitation in reality.

    It is slow (relatively), but for debugging I don't care. And so far I have been able to get by without generic metaprogramming, though it might be nice to have in the next version.

    By the way, thanks for maintaining/extending Jacob. It really has been a life-saver!

     
  • Jason Smith

    Jason Smith - 2007-11-21

    Logged In: YES
    user_id=1895760
    Originator: YES

    Another research project. More important that the core work flawlessly. :-)

     
  • Jason Smith

    Jason Smith - 2007-11-21
    • priority: 5 --> 4
     
  • clay_shooter

    clay_shooter - 2007-11-22

    Logged In: YES
    user_id=1189284
    Originator: NO

    This isn't a core function but is interesting. I'm not sure how many other libraries would use it.

    What is the simplest function that would help you with this? Do you have sample code you want converted to Java/COM and inserted?

     
  • Jason Smith

    Jason Smith - 2007-11-23

    Logged In: YES
    user_id=1895760
    Originator: YES

    I don't really have any sample code at this point. It would just be helpful for a number of things to be able to tell the type of the object at runtime. What interfaces it supports, what it's CoClass is...

    I really don't know what is possible in this area, so again, it's more of a research project if you get a wild hair. :-)

     

Log in to post a comment.