win32com: Setting ByRef parameters in an event

Paul Moore paul.moore at uk.origin-it.com
Fri Aug 24 09:18:04 EDT 2001


On Fri, 17 Aug 2001 01:32:46 +0200, Mark Hammond <MarkH at ActiveState.com>
wrote:

>Paul Moore wrote:
>>>   import win32com.client
>>>
>>>   class wexEvents:
>>>       def OnTick(self, Remaining, WakeUp):
>>>           print "Tick...", Remaining
>>>           return -1
>>>
>>>   wex = win32com.client.DispatchWithEvents("WshToolbox.WScriptEx",
>>>                                            wexEvents)
>>>
>>>   wex.Sleep(10000,1000)
>>>
>>>But this doesn't seem to work! 
>
>It should :(  The Excel etc demos all work fine with very similar 
>constructs.  You could try:
>
>    return 1==1
>
>which due to an implementation detail will ensure that a VT_BOOL is 
>returned - however, this should not be necessary.
>
>So no real clue I am afraid :(  If I could repro the error, I could 
>probably determine the problem.

Right, I've got it sorted. There are two separate issues:

1. The component was explicitly checking for VT_BOOL, rather than converting
whatever is sent. This is a component bug (and will be fixed). Using 1==1 to
force a VT_BYREF fixes this problem, but it would be nice to have a way (a
PyVARIANT type?) of explicitly passing a specific variant type.

2. The event handler needs *two* values returning. The first is sent to the
"result" of the IDispatch->Invoke() call, and the remaining are used to set
the ByRef parameters from the call. [This is in the source file
PyWin32\com\win32com\src\PyGatewayBase.cpp in function invoke_finish]

The problem with issue (2) is that it doesn't seem consistent - Mark comments
that the Excel tests work. I assume that this is because Excel's Connection
Point implementation passes a NULL for the pVarResult parameter of the
Invoke() method. However, ATL-generated COM objects pass a non-NULL
pVarResult, and use its scode (without checking for a type of VT_ERROR!) for
the HRESULT from the Fire_<event> call. [You can see this by generating a
trivial ATL project with an object implementing connection point support].

The big issue is that *no-one* is going to document this difference in
behaviour, so users are left with guesswork as the only way to know whether to
return an extra initial result.

I believe that win32com should ideally handle event methods specially, and
*ignore* the pVarResult for such methods (after all, events will always be
"logically" void procedures). The problem is that I can't see how it might be
possible, this far down in the infrastructure, to determine whether
PyGatewayBase::Invoke is being called from an event handler or a normal method
:-(

In the meantime, at least I have a workaround...

Phew!

Paul.




More information about the Python-list mailing list