win32, COM, and Solidworks (again) - Still Trying

Discussion in 'Python' started by Markus Wankus, Aug 7, 2003.

  1. I posted a looong time ago regarding this COM stuff (see the pasted post at
    the end) and I am still beating my head against the wall on this.

    I have been trying to debug this further and I think the root of my problem
    lies in win32com.client.__WrapDispatch(), pasted here:

    def __WrapDispatch(dispatch, userName = None, resultCLSID = None, typeinfo
    = None, \
    UnicodeToString = NeedUnicodeConversions, clsctx =
    pythoncom.CLSCTX_SERVER,
    WrapperClass = None):
    """
    Helper function to return a makepy generated class for a CLSID if it
    exists,
    otherwise cope by using CDispatch.
    """
    if resultCLSID is None:
    try:
    typeinfo = dispatch.GetTypeInfo()
    if typeinfo is not None: # Some objects return NULL, some raise
    exceptions...
    resultCLSID = str(typeinfo.GetTypeAttr()[0])
    except pythoncom.com_error:
    pass
    if resultCLSID is not None:
    import gencache
    # Attempt to load generated module support
    # This may load the module, and make it available
    klass = gencache.GetClassForCLSID(resultCLSID)
    if klass is not None:
    return klass(dispatch)

    # Return a "dynamic" object - best we can do!
    if WrapperClass is None: WrapperClass = CDispatch
    return dynamic.Dispatch(dispatch, userName, WrapperClass, typeinfo,
    UnicodeToString=UnicodeToString,clsctx=clsctx)


    For my objects, dispatch.GetTypeInfo() causes the following exception:

    Traceback (most recent call last):
    File "F:\_DEV\solidworks\swpycom.py", line 12, in ?
    print sw._oleobj_.GetTypeInfo()
    pywintypes.com_error: (-2147467263, 'Not implemented', None, None)

    Hmmm...'Not Implemented'. Because this fails, I can't obtain the CLSID of
    itself, thus it can't use the makepy generated code to bind itself
    properly. I always get back dumb CDispatch objects. I have been trying to
    hack a way of getting the CLSID of the dispatch object, but it just isn't
    there.

    Anyway - if anyone reading this knows anything about what I am talking
    about, your help would be greatly appreciated.

    Thanks,
    --
    Markus


    =============8< (old post) ===============
    Refer to: http://mail.python.org/pipermail/python-list/2003-May/161346.html

    win32com and early binding: Definitive answer? Markus Wankus
    Sat, 03 May 2003 12:24:14 -0400

    Hi all,
    I have been playing with Python and COM - attempting to talk to a 3D CAD
    package. I have posted on this before, and I have also had a lot of direct
    hints from Mark Hammond - but I am looking for a definitive answer to my
    problem here. I have seen other similar threads while Googling for a
    solution, but all of the answers were the same, with no real explanation as
    to why (at least nothing that I understand - being a COM newbie).
    Anyway - the problem is that the particular application (Solidworks)
    apparently refuses to use early binding. I have gone through the Python
    Programming on Win32 book with a fine-toothed comb but it just doesn't say
    anything about this sort of situation. Some code is in order:
    An example of early binding:
    import win32com.client
    sw = win32com.client.Dispatch('SldWorks.Application')
    print repr(sw)
    produces the output:

    '<COMObject SldWorks.Application>'
    OK - fine. No problem. Running makepy on the type library generates a
    module just fine, and it appears in the gen_py folder. So, technically
    this should force early binding:
    # Use these commands in Python code to auto generate .py support
    from win32com.client import gencache
    gencache.EnsureModule('{83A33D31-27C5-11CE-BFD4-00400513BB57}', 0, 10, 0)
    import win32com.client
    sw = win32com.client.Dispatch('SldWorks.Application')
    print repr(sw)
    which also produces the output:

    '<COMObject SldWorks.Application>'
    ARRGH! OK - well the file generated by makepy has the following in it:
    (...a whole bunch of crap...)
    class ISldWorks(DispatchBaseClass):
    """Interface for SolidWorks"""
    CLSID = pythoncom.MakeIID('{83A33D22-27C5-11CE-BFD4-00400513BB57}')
    (..various methods, etc...)
    And near the bottom of the file:
    # This CoClass is known by the name 'SldWorks.Application.10'
    class SldWorks(CoClassBaseClass): # A CoClass
    CLSID = pythoncom.MakeIID("{B49E4B36-A1A9-46A4-A738-545948A64113}")
    coclass_sources = [
    DSldWorksEvents,
    ]
    default_source = DSldWorksEvents
    coclass_interfaces = [
    ISldWorks,
    ]
    default_interface = ISldWorks
    (NOTE: 'SldWorks.Application.10' is a shortcut to 'SldWorks.Application' in
    the Registry. This is in case you have different versions instlled at the
    same time. Dispatching 'SldWorks.Application.10' produces the same
    results.)
    Various Google threads, as well as emails to me from Mark Hammond himself
    (which I very much appreciate - but this was awhile ago and I would like to
    put this to bed) has eluded to the fact that Solidworks does not implement
    IDispatch properly, which is the cause of my problems. I CAN get it to
    work by doing the following:
    # Use these commands in Python code to auto generate .py support
    from win32com.client import gencache
    sldmod = gencache.EnsureModule('{83A33D31-27C5-11CE-BFD4-00400513BB57}', 0,
    10, 0)
    import win32com.client
    sw = win32com.client.Dispatch('SldWorks.Application')
    sw = sldmod.ISldWorks(sw)
    print repr(sw)
    which produces the following output:
    <win32com.gen_py.SldWorks 2001plus Type Library.ISldWorks>
    The question is this: Is there ANY way to get around this without having
    to do the extra step of running that object through the interface? I could
    live with it if it was just the main application object - but I have to do
    this for every single Solidworks object I want to instantiate. So if a
    method of the application object returns a document object for instance, I
    have to look into the API and find out what type of object it is *supposed*
    to retun, tack an "I" on the front, and run it through its interface with:
    newObject = sldmod.I<real_object_name>(newObject)
    Which I could automate if I new the object type I was supposed to get back
    ahead of time - but I can't see a way to figure this out?
    I guess my only other option is to use something like SWIG to wrap the
    ..dll, or ctypes or something - but that seems like so much more work! Not
    to mention the fact that I don't know much about them either - so it may
    take me forever to figure those methods out as well.
    Anyway, as usual - any help would be greatly appreciated. FWIW - my next
    step is to get a definitive book on COM (not necessarily anything to do
    with Python) to learn more background. Perhaps there is a way in raw COM
    to handle this. Also - the docs for the Solidworks API say the following
    (if this helps):
    Programmer's Guide
    COM vs. Dispatch
    SolidWorks exposes its API functionality through standard COM objects. For
    OLE automation, the API is exposed using IDispatch.
    The Dispatch interface accepts and returns arguments as Variants and
    IDispatch pointers so they can be handled by languages such as Basic. All
    Visual Basic, VBA, or VC++ executable (.exe) implementations should use the
    Dispatch interface.
    A COM implementation gives your application direct access to the underlying
    objects or arrays, and subsequently, increased performance. COM
    implementations will provide slightly more functionality, with operations
    such as enumeration, and will also return an HRESULT value for each API
    function call. The COM interface is currently only available to VC++ add-in
    DLL implementations.
    The COM interface is recommended for all VC++ add-in DLL projects. If your
    product will be an .exe implementation, then you are required to use the
    Dispatch interface since custom marshaling is not provided.
    Which all sounds good - but it just doesn't work. I can provide
    ..tlb/.idl/gen_py files if anyone is really keen...
    Thanks ahead of time for any assistance,
    --
    Markus
    Markus Wankus, Aug 7, 2003
    #1
    1. Advertising

  2. On Thu, 07 Aug 2003 21:08:21 +1000, Mark Hammond
    <> wrote:

    > Markus Wankus wrote:
    >
    >> Hmmm...'Not Implemented'. Because this fails, I can't obtain the CLSID
    >> of itself, thus it can't use the makepy generated code to bind itself
    >> properly. I always get back dumb CDispatch objects. I have been trying
    >> to hack a way of getting the CLSID of the dispatch object, but it just
    >> isn't there.
    >>
    >> Anyway - if anyone reading this knows anything about what I am talking
    >> about, your help would be greatly appreciated.

    >
    > You should use code similar to:
    >
    > mod = gencache.EnsureModule("...", ...)
    >
    > ob = Dispatch("Whatever.Object")
    > # ob now "dumb dispatch", but should be object "foo"
    > # in the gencache module
    > # Explicitly convert ob to one of these object.
    > ob = mod.Foo(ob)
    >
    > Mark.
    >
    >


    Thanks, Mark. That's what I have been doing in the past (on your advice),
    but I have been trying to automate that process and found it next to
    impossible (from what I can figure out anyway). The reason this is an
    incredible pain is that every single method or attribute of 'ob' that
    returns an object, returns a dumb object. I need to know what class it is
    *supposed* to be, and run it through the gencache module class constructor.
    This is a huge pain.

    I realize this is nothing to do with win32all - it is Solidworks. Is there
    a way I can tell them about this problem and possibly get them to fix it?
    What have they not done in their C++ code that is making their
    implementation of COM so stupid?

    If there was a away I could make my own Dispatch class that forced this re-
    instantiation I would be happy, but I can't see any way to figure out what
    gencache class I need for a given object at runtime. I wonder if I could
    somehow generate my own, smarter module from scratch using the gencache
    module as a starting point. It would be incredibly painful...

    Anyway - thanks again for your help, Mr. Hammond. Perhaps I should let
    this drop already and accept the fact that it can't easily be done...

    --
    Mark
    Markus Wankus, Aug 7, 2003
    #2
    1. Advertising

  3. On Wed, 6 Aug 2003, Markus Wankus wrote:

    > For my objects, dispatch.GetTypeInfo() causes the following exception:
    >
    > Traceback (most recent call last):
    > File "F:\_DEV\solidworks\swpycom.py", line 12, in ?
    > print sw._oleobj_.GetTypeInfo()
    > pywintypes.com_error: (-2147467263, 'Not implemented', None, None)


    If you need to go beyond the IDispatch interface, Thomas Heller's ctypes
    package looks to be your only option, short of creating a full-blown
    Pythonwin wrapper (ala Pythonwin's MAPI support) for the SolidWorks COM
    API.

    Regards,
    Andrew.

    --
    Andrew I MacIntyre "These thoughts are mine alone..."
    E-mail: (pref) | Snail: PO Box 370
    (alt) | Belconnen ACT 2616
    Web: http://www.andymac.org/ | Australia
    Andrew MacIntyre, Aug 7, 2003
    #3
  4. On Thu, 7 Aug 2003 23:06:01 +1000 (EST), Andrew MacIntyre
    <> wrote:

    > On Wed, 6 Aug 2003, Markus Wankus wrote:
    >
    >> For my objects, dispatch.GetTypeInfo() causes the following exception:
    >>
    >> Traceback (most recent call last):
    >> File "F:\_DEV\solidworks\swpycom.py", line 12, in ?
    >> print sw._oleobj_.GetTypeInfo()
    >> pywintypes.com_error: (-2147467263, 'Not implemented', None, None)

    >
    > If you need to go beyond the IDispatch interface, Thomas Heller's ctypes
    > package looks to be your only option, short of creating a full-blown
    > Pythonwin wrapper (ala Pythonwin's MAPI support) for the SolidWorks COM
    > API.
    >


    Yes, I was looking into this but was a little mystified at first. I
    generated the python wrapper and had a look inside, but was unsure of the
    extent of the Python code I was going to be required to write, as well as
    type conversions.

    I guess I'll have another look at it. Thanks for the info.

    --
    Mark
    Markus Wankus, Aug 7, 2003
    #4
  5. Markus Wankus

    John J. Lee Guest

    Markus Wankus <> writes:

    > On Thu, 7 Aug 2003 23:06:01 +1000 (EST), Andrew MacIntyre
    > <> wrote:

    [...]
    > > If you need to go beyond the IDispatch interface, Thomas Heller's ctypes
    > > package looks to be your only option, short of creating a full-blown
    > > Pythonwin wrapper (ala Pythonwin's MAPI support) for the SolidWorks COM
    > > API.
    > >

    >
    > Yes, I was looking into this but was a little mystified at first. I
    > generated the python wrapper and had a look inside, but was unsure of
    > the extent of the Python code I was going to be required to write, as
    > well as type conversions.


    He wasn't talking about the automatically-generated makepy Python
    code, but rather hand-crafted C code wrapper around a particular
    vtable COM interface (though Mark may have some tools to help with the
    process of writing such wrappers, I don't think it's automated).

    ctypes is an easy way of doing it than writing a C wrapper.


    John
    John J. Lee, Aug 9, 2003
    #5
  6. On Mon, 11 Aug 2003 09:00:02 +1000, Mark Hammond
    <> wrote:

    > Markus Wankus wrote:
    >
    >> I realize this is nothing to do with win32all - it is Solidworks. Is
    >> there a way I can tell them about this problem and possibly get them to
    >> fix it? What have they not done in their C++ code that is making their
    >> implementation of COM so stupid?

    >
    > You could ask them to implement the type info interfaces for their
    > objects.
    >
    >> If there was a away I could make my own Dispatch class that forced this
    >> re-instantiation I would be happy, but I can't see any way to figure out
    >> what gencache class I need for a given object at runtime.

    >
    > Yes, this is the rub.
    >


    Thanks, again - Mark. I'll try to see if they will listen to suggestions
    for future releases...

    --
    Markus
    Markus Wankus, Aug 11, 2003
    #6
  7. On 09 Aug 2003 15:21:44 +0100, John J. Lee <> wrote:

    > Markus Wankus <> writes:
    >
    >> On Thu, 7 Aug 2003 23:06:01 +1000 (EST), Andrew MacIntyre
    >> <> wrote:

    > [...]
    >> > If you need to go beyond the IDispatch interface, Thomas Heller's

    >> ctypes
    >> > package looks to be your only option, short of creating a full-blown
    >> > Pythonwin wrapper (ala Pythonwin's MAPI support) for the SolidWorks

    >> COM
    >> > API.
    >> >

    >>
    >> Yes, I was looking into this but was a little mystified at first. I
    >> generated the python wrapper and had a look inside, but was unsure of
    >> the extent of the Python code I was going to be required to write, as
    >> well as type conversions.

    >
    > He wasn't talking about the automatically-generated makepy Python
    > code, but rather hand-crafted C code wrapper around a particular
    > vtable COM interface (though Mark may have some tools to help with the
    > process of writing such wrappers, I don't think it's automated).
    >
    > ctypes is an easy way of doing it than writing a C wrapper.
    >


    Hmmm.. I guess I am not following. I'll go back to the ctypes page again
    and give it another go.

    Thanks,
    --
    Markus
    Markus Wankus, Aug 11, 2003
    #7
  8. Markus Wankus

    John J. Lee Guest

    Markus Wankus <> writes:

    > On 09 Aug 2003 15:21:44 +0100, John J. Lee <> wrote:
    >
    > > Markus Wankus <> writes:
    > >
    > >> On Thu, 7 Aug 2003 23:06:01 +1000 (EST), Andrew MacIntyre
    > >> <> wrote:

    > > [...]
    > >> > If you need to go beyond the IDispatch interface, Thomas Heller's
    > >> ctypes
    > >> > package looks to be your only option, short of creating a full-blown
    > >> > Pythonwin wrapper (ala Pythonwin's MAPI support) for the
    > >> SolidWorks COM
    > >> > API.
    > >> >
    > >>
    > >> Yes, I was looking into this but was a little mystified at first. I
    > >> generated the python wrapper and had a look inside, but was unsure of
    > >> the extent of the Python code I was going to be required to write, as
    > >> well as type conversions.

    > >
    > > He wasn't talking about the automatically-generated makepy Python
    > > code, but rather hand-crafted C code wrapper around a particular
    > > vtable COM interface (though Mark may have some tools to help with the
    > > process of writing such wrappers, I don't think it's automated).
    > >
    > > ctypes is an easy way of doing it than writing a C wrapper.
    > >

    >
    > Hmmm.. I guess I am not following. I'll go back to the ctypes page
    > again and give it another go.


    Ah, maybe it was me who wasn't following. I haven't looked at the
    ctypes COM support. I was thinking you were referring to the
    win32all-generated Python code, but maybe ctypes does Python code
    generation too, and you were referring to that? Dunno.


    John
    John J. Lee, Aug 12, 2003
    #8
  9. On 12 Aug 2003 01:12:29 +0100, John J. Lee <> wrote:

    > Markus Wankus <> writes:
    >
    >> On 09 Aug 2003 15:21:44 +0100, John J. Lee <> wrote:
    >>
    >> > Markus Wankus <> writes:
    >> >
    >> >> On Thu, 7 Aug 2003 23:06:01 +1000 (EST), Andrew MacIntyre
    >> >> <> wrote:
    >> > [...]
    >> >> > If you need to go beyond the IDispatch interface, Thomas Heller's
    >> >> ctypes
    >> >> > package looks to be your only option, short of creating a full-

    >> blown
    >> >> > Pythonwin wrapper (ala Pythonwin's MAPI support) for the
    >> >> SolidWorks COM
    >> >> > API.
    >> >> >
    >> >>
    >> >> Yes, I was looking into this but was a little mystified at first. I
    >> >> generated the python wrapper and had a look inside, but was unsure of
    >> >> the extent of the Python code I was going to be required to write, as
    >> >> well as type conversions.
    >> >
    >> > He wasn't talking about the automatically-generated makepy Python
    >> > code, but rather hand-crafted C code wrapper around a particular
    >> > vtable COM interface (though Mark may have some tools to help with the
    >> > process of writing such wrappers, I don't think it's automated).
    >> >
    >> > ctypes is an easy way of doing it than writing a C wrapper.
    >> >

    >>
    >> Hmmm.. I guess I am not following. I'll go back to the ctypes page
    >> again and give it another go.

    >
    > Ah, maybe it was me who wasn't following. I haven't looked at the
    > ctypes COM support. I was thinking you were referring to the
    > win32all-generated Python code, but maybe ctypes does Python code
    > generation too, and you were referring to that? Dunno.
    >
    >
    > John
    >


    Yeah - ctypes generates Python code as well and that is what I was
    referring to. Anyway - thanks to all who responded. I just wish I knew a
    little more...ah well. You can't beat experience. Too bad it takes so
    long.

    --
    Markus
    Markus Wankus, Aug 12, 2003
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. amit
    Replies:
    0
    Views:
    388
  2. che
    Replies:
    2
    Views:
    492
  3. luqman
    Replies:
    20
    Views:
    954
    Juan T. Llibre
    Jul 6, 2007
  4. luqman
    Replies:
    0
    Views:
    339
    luqman
    Jul 5, 2007
  5. Aaron
    Replies:
    2
    Views:
    196
    Jano Svitok
    Jul 27, 2007
Loading...

Share This Page