[python-win32] errors running C++ client against python COM server

Impert, Nicky P nicky.p.impert at boeing.com
Mon Oct 17 23:39:50 CEST 2005


Mark, thanks for getting back to me.  Note, I have since also tried
getting a python COM server using package ctypes to connect to a C++ COM
client using event handlers and found I could do it with a dispatch
interface (dispinterface in idl), but not a custom interface (inherited
from IUnknown).  Can someone tell me if it is possible to call an event
handler on a client from python using a custom interface (w/ or w/out
ctypes)?  If so, can someone show me an example?

Here is the error log from the default python client (only try to
connect from the C++ client if the python client is still happy):
python client.py
create instance of server
pythoncom error: ERROR: server.policy could not create an instance.

Traceback (most recent call last):
  File "C:\Python24\Lib\site-packages\win32com\server\policy.py", line
144, in CreateInstance
    return retObj._CreateInstance_(clsid, reqIID)
  File "C:\Python24\Lib\site-packages\win32com\server\policy.py", line
203, in _CreateInstance_
    self._wrap_(myob)
  File "C:\Python24\Lib\site-packages\win32com\server\policy.py", line
468, in _wrap_
    tlb_major, tlb_minor, interfaces)
  File "C:\Python24\Lib\site-packages\win32com\universal.py", line 54,
in RegisterInterfaces
    raise ValueError, "Interface '%s' does not exist in this cached
typelib" % (name,)
exceptions.ValueError: Interface
'{F51A6858-F43E-4CF9-B603-6D15D3E8DB71}' does not exist in this cached
typelib
pythoncom error: Unexpected gateway error

Traceback (most recent call last):
  File "C:\Python24\Lib\site-packages\win32com\server\policy.py", line
144, in CreateInstance
    return retObj._CreateInstance_(clsid, reqIID)
  File "C:\Python24\Lib\site-packages\win32com\server\policy.py", line
203, in _CreateInstance_
    self._wrap_(myob)
  File "C:\Python24\Lib\site-packages\win32com\server\policy.py", line
468, in _wrap_
    tlb_major, tlb_minor, interfaces)
  File "C:\Python24\Lib\site-packages\win32com\universal.py", line 54,
in RegisterInterfaces
    raise ValueError, "Interface '%s' does not exist in this cached
typelib" % (name,)
exceptions.ValueError: Interface
'{F51A6858-F43E-4CF9-B603-6D15D3E8DB71}' does not exist in this cached
typelib
pythoncom error: CPyFactory::CreateInstance failed to create instance.
(80004005)
Traceback (most recent call last):
  File "client.py", line 72, in ?
    test(1)
  File "client.py", line 54, in test
    server = win32com.client.dynamic.Dispatch("Python.MyEventServer")
  File "C:\Python24\Lib\site-packages\win32com\client\dynamic.py", line
98, in Dispatch
    IDispatch, userName =
_GetGoodDispatchAndUserName(IDispatch,userName,clsctx)
  File "C:\Python24\Lib\site-packages\win32com\client\dynamic.py", line
91, in _GetGoodDispatchAndUserName
    return (_GetGoodDispatch(IDispatch, clsctx), userName)
  File "C:\Python24\Lib\site-packages\win32com\client\dynamic.py", line
79, in _GetGoodDispatch
    IDispatch = pythoncom.CoCreateInstance(IDispatch, None, clsctx,
pythoncom.IID_IDispatch)
pywintypes.com_error: (-2147221231, 'ClassFactory cannot supply
requested class', None, None)

the python client code reads:
# Implements a connectable client.
#
# Initial client code extracted from
# C:\Python24\Lib\site-packages\win32com\demos\connect.py

import pythoncom
import win32com.server.util
import win32com.server.connect
from win32com.server.exception import Exception

# This is the IID of the Events interface both Client and Server
support.
IID__IConnectDemoEvents =
pythoncom.MakeIID("{FCA56F6D-2291-4A32-9BDE-D577D24616F1}")

# Here is the client side of the connection world.
# Define a COM object which implements the methods defined by the
# IConnectDemoEvents interface.
class ConnectableClient:
        # This is another cheat - I _know_ the server defines the
"DoneIt"
        # event as DISPID==1000 - I also know from the implementation
details
        # of COM that the first method in _public_methods_ gets 1000.
        # Normally some explicit DISPID->Method mapping is required.
        _public_methods_ = ["OnDoneIt"]
        def __init__(self):
                self.last_event_arg = None
        # A client must implement QI, and respond to a query for the
Event
        # interface.  In addition, it must provide a COM object.
        # This is provided by server.util.wrap().
        def _query_interface_(self, iid):
                import win32com.server.util
                # Note that this seems like a necessary hack.
                # I am responding to IID__IConnectDemoEvents
                # but only creating an IDispatch gateway object.
                if iid==IID__IConnectDemoEvents: return
win32com.server.util.wrap(self)
        # And here is our event method which gets called.
        def OnDoneIt(self, arg):
                self.last_event_arg = arg

def CheckEvent(server, client, val, verbose):
        client.last_event_arg = None
        server.DoIt(val)
        if client.last_event_arg != val:
                print "Sent %r, but got back %r" % (val,
client.last_event_arg)
        elif verbose:
                print "Sent and received %r" % val

# A simple test script for all this.
# In the real world, it is likely that the code controlling the server
# will be in the same class as that getting the notifications.
def test(verbose=0):
        import win32com.client.dynamic, win32com.client.connect
        import win32com.server.policy
        print "create instance of server"
        server =
win32com.client.dynamic.Dispatch("Python.MyEventServer")
        print "create instance of client"
        client = ConnectableClient()
        print "connect client to server (1 of 2)"
        connection = win32com.client.connect.SimpleConnection()
        print "connect client to server (2 of 2)"
        connection.Connect(server, client, IID__IConnectDemoEvents)
        CheckEvent(server, client, "Hello", verbose)
        if verbose:
                print "Everything seemed to work!"
        # Aggressive memory leak checking (ie, do nothing!)
        # :-)  All should cleanup OK???

if __name__=='__main__':
        test(1)


More information about the Python-win32 mailing list