[python-win32] Yet another person confused on static versus dynamic dispatch

Red Gator redgatormds at gmail.com
Thu May 8 17:14:04 CEST 2014


I have 29 years of professional experience with UNIX (can you say BSD 4.3
Tahoe, where I was manufacturing the "Tahoe" architecture?) Once upon a
time I cared nothing for Windows and it's ilk, and nobody demanded that I
do..And life was good.

Then I get assigned to this project which is written entirely in Python.
That's OK, Python had been on my list for a long time. And Python on UNIX
AND freaking Windows? Well, with a dose of Cygwin and some well-implemented
Python on the Windows box, I think I can manage...

Then I have a request to get this Windows-only application named FalconView
(http://www.falconview.org) to talk to the application. How is that done?
Windows COM interfaces. Nail me to the perch now...

Everything I know about COM I have learned from pywin32 and Mr Mark
Hammond. Thank you, Mr Hammond, this is brilliant. Although it does feel
somewhat like meeting an iceberg in almost exactly the wrong way.

With the help of "The Book" (being a Uni Florida Gator, I rather appreciate
the crocodilian on the cover), I managed to makepy.py the TLB of the
FalconView automation (almost like I know what I'm talking about), and got
many of  the features working well enough to be usable. I've been able to
demonstrate functionality and gotten past a proof-of-concept, and now am on
my way to making something real (wink, wink, nuff said, say-no-more).

I'm re-factoring the code now to get access to more interactive features
(what's a GUI without interaction?) and smacked into many APIs I could not
make work. I even hand-jiggered the file makepy.py created to get past some
issues, but then I smacked into a brick wall too high and too long to get
over or around.

Searching desparately for a solution, I found a discussion that made sense
out of this diagnostic output:

Map.com=<win32com.gen_py.None.Map>
...
Layer.com=<COMObject FalconView.Layer>


Apparently this means "Map.com is static dispatch and Layer.com is not".
(Pg 205 - not quite the same thing) So methods in Layer.com could be
refered to without regard to case and Map.com could not (see, I've learned
something!) And apparently there is not enough type information in the TLB
to make the dynamic dispatch work properly, so things like this from
Layer.com (from OLE/COM Viewer... oh, the evil things I'm learning...):

[id(0x00000016)]
long GetVersion(
                short* major,
                short* minor,
                short* revision);


Could not be made to work (always get "Type mismatch").

With things like this is Map.com:

[id(0x00000010)]
long GetMapDisplay(
                double* lat,
                double* lon,
                double* rotation,
                long* category,
                long* map_handle,
                long* zoom,
                long* projection_type);


The latter has worked brilliantly from day one.

I had Map.com defined this way:

from win32com.server.util import wrap, unwrap

import win32com.client
import pythoncom
import win32ui



        self.mapClass =
win32com.client.gencache.GetClassForProgID("FalconView.Map")
        self.com = self.mapClass()

I had Layer.com defined this way:

self.com = win32com.client.Dispatch("FalconView.Layer")


I do recall thrashing around a good bit trying to get started. Map came
before Layer (Layer objects go over the top of Map objects),  "The Book"
around page 200 could probably have deserved a whole chapter.Reviewing
what's there I can't quite tell you how I came upon this code as a
solution; they BOTH look WRONG now.

I recently came across this posting (Mark Hammond — 12/17/2013 5:11:59 AM):

ob = win32com.client.Dispatch("The.ClassId")

at which point 'ob' is going to be a "dumb dispatch" object as it can't

find the typelib.  Then, if you ran makepy "normally" you could do:

kls = win32com.client.gencache.GetClassForProgID("The.ClassId")

# wrap the dumb object in the generated class

ob = kls(ob)


which splits the difference between my two implementations.

Sure I can do that. But after this debacle I find I need to know "why".


   - Why does my object come up as "win32com.gen_py.None.Map" when it
   should come up as 'win32com.gen_py.<<fiddly-GUID-bits>>.Map or even
   "win32com.gen_py.<<library-descriptiojn-with-dots>>.Map. There was some
   comment that in this state the object would be unusable, whereas this is
   the object that I have found actually usable.
   - Pg 203 "Dispatch()  [checks] to see if MakePy support exists for the
   object". Well, I KNOW that the MakePy file is being referenced because I've
   made manual changes to it and have had those changes show up as new
   behavior in the application. So why doesn't the Layer.com = Dispatch() work
   as described?
   - What is the necessity in the posting where the COM object class is
   derived from the Dispatch() object, which I don't appear to be doing in the
   working case?

I think that's enough for now. Time for some eggs and spam...
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-win32/attachments/20140508/30c1024a/attachment.html>


More information about the python-win32 mailing list