Greetings.  I need a working example of implementing an event handler in
a C++ client with a python server.  I broke apart the python connect
example into a client and server.  (i.e. I split
C:\Python24\Lib\site-packages\win32com\demos\connect.py into client.py
and server.py in some other directory.)  I then changed the guids of
server.py.  I added this directory to my PYTHONPATH environment
variable.  I then created an idl file to match the interface as best I
could.  I compiled the idl file with visual studio's midl tool to get a
header and tlb file and I wrote a C++ client against the generated
header and tlb file.

When I register the python server and run the python client, everything
works fine.  Running the C++ client gave me errors, so I tried to add
additional information from the idl file to the python server (the idl
file requires 4 uuids, but initially server.py as copied from connect.py
only had 2).  The python client still works, the C++ client does not.
What I would like to know is if I need to add or change anything else in
the python server or the derived idl file, or should they work with a
C++ client as written.  The typelib guid is currently defined as a
top-level _reg_clsid_ as opposed to _typelib_guid_ within the coclass
because if I set this parameter in server.py, client.py fails.

Below is a printout of the output of both clients as well as the source
of server.py and the implied idl file MyEventServer.idl:

Any help much appreciated, --Nicky Impert

>python server.py
Registered: Python.MyEventServer
>python client.py
I am being called
Sent 'Hello', but got back u'Hello_suffix'
Everything seemed to work!

still works, but when I run by C++ client, I get:
'ConnectionClient.exe': Loaded
'C:\Python24\Lib\site-packages\win32\win32trace.pyd', No symbols loaded.
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
211, in _CreateInstance_
    raise pythoncom.com_error, (hr, desc, exc, arg)
pywintypes.com_error: (-2147467262, "The object
'<server.MyConnectableServer instance at 0x01483B48>' was created, but
does not support the interface
'IConnectableServer'({F51A6858-F43E-4CF9-B603-6D15D3E8DB71}): No such
interface supported", None, None)
pythoncom error: Unexpected gateway error

Traceback (most recent call last):
(. . . -- above traceback info repeats)
pythoncom error: CPyFactory::CreateInstance failed to create instance.
(80004005)

---- server.py ----
# Implements a connectable server.
#
# Initial server code extracted from
# C:\Python24\Lib\site-packages\win32com\demos\connect.py
# then embellished in an attempt to allow a C++ client to exercise it.

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}")
IID_IConnectableServer =
pythoncom.MakeIID("{F51A6858-F43E-4CF9-B603-6D15D3E8DB71}")

# putting typelib guid up here as top-level reg_clsid because I have
# seen it done this way before, and uncommenting _typelib_guid_ causes
# the client to fail.
_reg_clsid_ = "{3593F5DE-2F61-43E9-8788-68D2D4C943D8}"
_reg_libname_ = "server Typelib"

# The server which implements
# Create a connectable class, that has a single public method
# 'DoIt', which echos to a single sink 'DoneIt'

class MyConnectableServer(win32com.server.connect.ConnectableServer):
        """Interface MyConnectableServer"""

        _public_methods_ = ["DoIt"] +
win32com.server.connect.ConnectableServer._public_methods_
        _reg_progid_ = "Python.MyEventServer"
#        _reg_verprogid_ = "Python.MyEventServer.1"
        _reg_clsid_ = "{FA5F6400-DD37-4E1D-9E2C-9BEC56C4F2AE}"
        _reg_desc_ = "Python Event Server (test server -- returns
string)"
        _reg_class_spec_ = "server.MyConnectableServer"
#        _reg_policy_spec_ =
"win32com.servers.EventServer.SingletonPolicy"

        # uncommenting these lines causes client.py to fail
#        _typelib_guid_ = "{3593F5DE-2F61-43E9-8788-68D2D4C943D8}"
#        _typelib_version_ = 0, 1
        _connect_interfaces_ = [IID__IConnectDemoEvents]
        _com_interfaces_ = [IID_IConnectableServer] +
win32com.server.connect.ConnectableServer._com_interfaces_

        # The single public method that the client can call on us
        # (ie, as a normal COM server, this exposes just this single
method).
        def DoIt(self,arg):
                # Simply broadcast a notification.
                print "I am being called"
                arg = arg + "_suffix"
                self._BroadcastNotify(self.NotifyDoneIt, (arg,))

        def NotifyDoneIt(self, interface, arg):
                interface.Invoke(1000, 0, pythoncom.DISPATCH_METHOD, 1,
arg)

if __name__=='__main__':
        import win32com.server.register
        win32com.server.register.UseCommandLine(MyConnectableServer)

---- MyEventServer.idl ----
///////////////////////////////////////////////////////////////////
// This file (MyEventServer.idl) was written to match up with the
// implied definition in server.py
//
// To produce a type library (.tlb) just run 'midl' on this file.
//
import "oaidl.idl";
import "ocidl.idl";
// Interface IConnectableServer:
[
    object,
    uuid(F51A6858-F43E-4CF9-B603-6D15D3E8DB71),
    dual,
    helpstring("IConnectableServer Interface"),
    pointer_default(unique)
]
interface IConnectableServer : IDispatch
{
    [id(1000), helpstring("method DoIt")] HRESULT DoIt([in] BSTR arg);
};

///////////////////////////////////////////////
// Type Library:
[
    // Every class of the form "CFoo" must contain the class attribute
    //    _typelib_guid_ = "{3593F5DE-2F61-43E9-8788-68D2D4C943D8}"
    uuid(3593F5DE-2F61-43E9-8788-68D2D4C943D8), // top level _reg_clsid_
    version(0.1),
    helpstring("server 0.1 Type Library")
]
library MyEventServerLib
{
    importlib("stdole32.tlb");
    importlib("stdole2.tlb");
    // callback (event handler) OnDoneIt
    [
        uuid(FCA56F6D-2291-4A32-9BDE-D577D24616F1),
        helpstring("_IConnectDemoEvents Interface")
    ]
    interface _IConnectDemoEvents : IUnknown
    {
        [id(1000), helpstring("method OnDoneIt")] HRESULT OnDoneIt(BSTR
Result);
    }
    // Class MyConnectableServer:
    [
        // The Python class MyConnectableServer must contain this class
attribute:
        uuid(FA5F6400-DD37-4E1D-9E2C-9BEC56C4F2AE), // _reg_clsid_
        helpstring("server MyConnectableServer Class")
    ]
    coclass MyConnectableServer  // _reg_progid_
    {
        [default] interface IConnectableServer;
        [default, source] interface _IConnectDemoEvents;
    };
};
_______________________________________________
Python-win32 mailing list
Python-win32@python.org
http://mail.python.org/mailman/listinfo/python-win32

Reply via email to