[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