Exporting events from Python COM class.

shindich at my-deja.com shindich at my-deja.com
Mon Nov 13 23:45:35 EST 2000


In article <8ujetu01u8b at news1.newsguy.com>,
  "Alex Martelli" <aleaxit at yahoo.com> wrote:
> "Syver Enstad" <syver.enstad at sensewave.com> wrote in message
> news:8ui9bt$cf1$1 at troll.powertech.no...
>     [snip]
> > > just won't fly -- the client-object trying to connect is
> > > always queried for the *first* interface in the list, so
>     [snip]
> > Is this similar to the bug in IE5.0 HTMLDocument Advise
implementation
> > where you try to  sink the events for DHTMLDocumentEvents2 but IE
insists
> on
> > firing the events for DHTMLDocumentEvents on your object that
implements
> > DHTMLDocumentEvents2 causing no end of grief?
>
> Sorry, I'm not familiar with this specific bug (any URL please...?),
> although from your summary description it does sound like it
> might have a similar root-cause!
>
> > You mean that if I implement f.ex a C++ object that implements two
> IDispatch
> > interfaces and one of them is a sink for a python implemented COM
object,
> > Python will screw up and call the wrong Dispatch interface? (Like in
the
> IE
> > example that I've lined up above?)
>
> It might, yes, but it's slightly subtler than that.
>
> A single C++ object cannot implement two _fully separate_ "IDispatch
> interfaces".  It can implement two interfaces _derived_ from
IDispatch,
> sure, but the part they have in common (the first 7 methods -- 3 from
> IUnknown, 4 from IDispatch proper) will have only one implementation.
>
> The C++ reason is that override resolution is by-name.  The C++
> object can have only one method named Invoke (with the appropriate
> signature), for example.  Now, suppose both dispinterfaces have
> (different) methods with a dispatch-id of 1.  If a client calls Invoke
> on the C++ object with a dispid of 1, there is no context left to
> tell WHICH of the methods that the different dispinterfaces mean
> by 'dispid 1' is intended.  I sketched a simplified but broad picture
> of this issue over different object-models (Java, C++, VB, Python,
> COM) in a recent article on this group, on a thread about interfaces
> in Python vs Java.
>
> COM to the rescue: a "COM object" does NOT have to correspond
> to *just ONE* C++ object.  You can piece together a COM object
> out of as many C++ objects as suits you (including ones built on
> the fly in response to QueryInterface, with or without caching...
> this is called "the tear-off technique"), as long as they respect
> certain rules (return identical results when QI'd IID_IUnknown,
> return logically-equivalent results when QI'd for anything else).
>
> (For ATL support for these advanced techniques, see, on MSDN,
> the "COM_INTERFACE_ENTRY Macros" article, and the details
> on COM_INTERFACE_ENTRY_AGGREGATE and its ilk; Don Box's
> works, particularly "Essential COM", explain very well the COM
> identity rules & their reasons and implications, IMHO -- you can
> find many of his articles on MSDN, the "House of COM" column).
>
> Note that if a counterpart queries your object (along any
> interface) for IID_IDispatch specifically, you must always
> give one and the same answer -- no fudging (returning
> logically-different dispatch's depending on what interface
> is queried for them), or you'll regret it eventually...
>
> OK, so, suppose you _have_ gone to the trouble of carefully
> placing the implementation of two (or more) dispinterfaces
> in a C++-implemented COM object _in different C++ objects_,
> and now use connectionpoints, eventually Advise, to place
> that object as a listener for another object's events along
> one such dispinterface.  Will it work?  It should -- unless the
> other object has bugs.
>
> (Note that this is *DIFFERENT* from _general_ use of your
> multi-dispinterfaces object from scripting -- in THAT case,
> the script has full rights to QI your object for IID_IDispatch,
> and will likely do so, particularly if proxies/stubs or any
> other kind of marshaling are involved; for THAT case, you
> definitely need different COM identities...!!!).
>
> Python had a little such bug.  It's fixed with the 1-line-change
> to connect.py which Mark suggested -- I tested it.  However,
> connect.py as it stands (even after the fix) does *NOT* support
> a server object that wants to expose two separate source
> interfaces -- for that, the connect-helper must expose separate
> connection-point objects... it's not rocket science, but it takes
> some work (and may easily produce circular references, of
> a slightly-nasty kind... oh for WEAK references...!!!).
>
> On how to get different COM identities (so your single
> object can usefully serve scripts along different interfaces,
> when scripting languages only know to QI for IDispatch):
> it's actually much easier than it sounds!  I have a little
> collection of auxiliary COM objects for such purposes,
> called Au.Dll (it's worth its weight in gold, and contains
> AUxiliary objects to implement COM AUtomation, so...),
> which provides for that as well as a few more useful
> things.  Unfortunately, I developed it at work, for work,
> so I can't just go and publish it (I'd need a bureaucratic
> nod of approval for that -- quite a bother...) -- but I
> guess I might rewrite and publish such parts as the
> COM-identity-masker (they'd be opensourced C++ code
> using ATL 3 and MSVC++ 6) if there was interest.
>
> Alex
>
>
Speaking of Weak References... I'm working on a project that provides a
C++ extension object that works as a weak reference.
Pre-alpha release of PyWeakReference project is now available on Source
Forge (http://sourceforge.net/projects/pyweakreference/)
I'll post good docs in a couple of days. I just never had time to finish
it up.(some docs are available in the Doc subdirectory of the zip file)

Enjoy!
Alex Shindich
Visit http://www.shindich.com/


Sent via Deja.com http://www.deja.com/
Before you buy.



More information about the Python-list mailing list