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) _______________________________________________ Python-win32 mailing list Python-win32@python.org http://mail.python.org/mailman/listinfo/python-win32