Exporting events from Python COM class.

Mark Hammond MarkH at ActiveState.com
Fri Nov 10 07:01:01 EST 2000


Alex Martelli wrote:

>> And actually exposes the reason for one of the hacks in win32com.
>> Notice the second arg to the first QI.  This is to say "even though I am
>> QIing for an interface you dont support, give me back an object anyway".
> 
> 
> But why?  If the client is trying to connect an object that
> does *not* "sink" (=="is able to be called on") the specified
> events-interface (which the server "sources" == "calls methods on"),
> then we do NOT want Advise to succeed!

I worded this poorly.  I should have said "if the QI succeeds but the 
PythonCOM extensions do not provide explicit support for the interface, 
return an IUnknown anyway".

ie, the "1" is _not_ preventing a DISP_E_NOINTERFACE error, rather some 
"internal" error telling you that Python doesnt support the interface.

Actually, the "1" is the old API - the new interface is the IID of the 
object you want back instead!  1 == IUnknown for b/w compat (probably 
for this code :-)

Thus, I _think_ you could get the behaviour you want by changing the "1" 
to IID_IDispatch, and removing the second QI.

> Events-interfaces are almost invariably dispinterfaces: the
> methods are exactly those of IDispatch, only the IID differs.

I agree 100% - but the "almost" is what has me worried ;-)


> Some COM background (which I'm sure you don't need, but may come
> in handy for some readers!):

Thanks - and to my mind, is exactly the reason why I _dont_ want to 
break the rules here!  You QI for an IID, you get back a pointer to that 
interface.  No where does it say "oh - but you may _really_ get back an 
IDispatch that happens to implement an object model as described by that 
IID".  It is pretty clear you get a pointer to that interface.

> *sigh* that silly example has done MUCH harm.  Please refer
> to all Microsoft literature on the subject... for example,
> "Dr. GUI and COM Events, Part 1", its August 23, 1999 column
> (it's in MSDN, of course), rightly says "It doesn't make
> sense for a source interface to be a dual interface".

Thanks!

Jeez - MS are full of it.  On one hand, as you say, they write "It 
doesn't make sense for a source interface to be a dual interface".  But 
the _same_ paragraph says "If you want to have an event interface that 
can be high performance and compatible with Visual Basic, ...".

So really, they are saying there _is_ good reason to do this, but it is 
not compatible with VB.

*sigh*.  Other Python COM stuff exists purely for VB, and I guess this 
qualifies as the documentation I asked Toby for...

OTOH, I see their point.  This exact same limitation is exactly what 
Python needs to do to work.

> 
> COM QI rules are inviolable, and the Box-and-others
> article I quote above is one of the clearest I know
> on the subject.

Well I am still missing something :-(  I thought it was pretty clear 
that when you did a QI, you got back what was effectively a vtable 
describing that interface.  I thought COM was a binary standard, and 
this was fundamental.

Am I free to return an IDispatch in _any_ QI for _any_ IID, as long as I 
return a faithful IDispatch for the interface?  Or does this only apply 
to sinks?

>> Hence we have the second QI for specifically IDispatch.
> 
> But you won't necessarily get the "same Dispatch" (Invoke
> with the same semantics) as you should have in the
> dispinterface you're QI'ing.  Again, I hope the Box-et-al
> article makes that cristal-clear.

I definitely see the point you are making.  I just see it as a gross 
violation of clear rules.  However, you have given me plenty of 
references to make it clear it must just be me!

> I _think_ the right approach would be as follows: if
> the interface is "known" (from previous makepy's) it
 > can be used anyway; else, it must be a dispinterface

The behaviour really should be identical regardless of makepy.  Not 
having makepy will mean we have trouble _implementing_ the interface, 
and _may_ have trouble calling it in some cases, the but basic behaviour 
shouldnt really be dependent?

ie, from what you pointed me at above and from your and Toby's 
assertions, it must be a dispinterface, period.  Otherwise it is in 
"gross violation" of "conventions" (as opposed to "rules" :-)

> Consider the following example (ATL 3.0) -- the IDL
> being:

As I said, I always understood the concern.  However, I now yield, 
because as Toby says it has come up before, and you chiming in leaves me 
with no reasonable defence.

So patches welcome ;-)

Mark.




More information about the Python-list mailing list