[python-win32] Python COM Server, C++ Client - How ???

Aviel, Gal gal.aviel at intel.com
Fri Sep 21 12:05:55 CEST 2007


Hi,

After searching for two days now, I could not find a simple recepie to on how 
to connect to a python local com server (exe) from a C++ client (VC6.0). Note 
that eventually I would want to package my server using py2exe, however even 
without this step - it doesn't work. 

I'm getting kind of desperate since this means the code I've worked on is 
useless since the software guys can't connect to it from C++. I've counted on 
Python to do the trick but now I see it's not that simple and maybe not 
possible.

Below you can find a simple example for a Python COM local server (exe) that 
has only 1 method - Add() - to add 2 integers and return the result.

I've written the IDL file, compiled it with MIDL, and included into the C++, 
as explained in http://www.codeproject.com/com/LocalCOMServerClient.asp.

The part most confusing is the differnt GUID numbers (type library, class, and 
interface) and exactly where to put what. Specifically, where should the value 
entered in '_reg_clsid_' (python) fit in the IDL file? and where to take
the 2 other GUID's that should be entered in the IDL file?

Also, Visual Studio OLE Viewer, I saw "Python Com Server" (and the PTCS 
interface under it after I register PTCS.py), will that be present or required 
in py2exe environmetn where there is no python installation?

In addition, how can I make my server show in PythonWin's 'MakePy' utility 
or 'COM Browser'?

Any help would be greatly appreciated, I'd later post the clean example for 
anyone to use.

Thanks in advance - Gal.

# ----------------------------
# PTCS.py
# ----------------------------
# PTCS == Python Test Com Server
# small local server (out of process) python com server, try to connect from 
C++ client (VC++6.0 client)

import win32com.server.register
import pythoncom

class PTCS:
    """
    PTCS - Python Test Com (local) Server 
    has only 1 simple function - Add - to add two int's and return the result.
    """
    _public_methods_ = [ 'Add' ]
    _reg_progid_     = "PTCS"
    _reg_clsid_      = "GUID1"            # ------- GUID1 -----------
    _reg_clsctx_     = pythoncom.CLSCTX_LOCAL_SERVER
    def __init__(self):
        pass
    def Add(self,a,b):
        """ add the 2 passed integeres. """
        return a+b
if __name__ == '__main__':
    win32com.server.register.UseCommandLine(PTCS, debug=True)

# ----------------------------
# PTCS.idl
# ----------------------------
// PTCS.idl : IDL source for PTCS.dll
//
// This file will be processed by the MIDL tool to
// produce the type library (PTCS.tlb) and marshalling code.

import "oaidl.idl";
import "ocidl.idl";

[
	object,
	uuid(GUID1),			// ---- GUID1 --------
	dual,
	helpstring("PTCS Com Interface"),
	pointer_default(unique)
]
interface ICoPTCS : IDispatch
{
	[id(1), helpstring("method Add: add 2 integers")] HRESULT Add([in] 
int* a, [in] int* b, [out, retval] int* res );
};


[
	uuid(GUID2),			// ---- GUID2 --------
	version(1.0),
	helpstring("PTCS 1.0 Type Library")
]
library PTCSLib
{
	importlib("stdole32.tlb");
	importlib("stdole2.tlb");
[
	uuid(GUID3),			// ---- GUID3 --------
	helpstring("CoPTCS Class")
]
coclass CoPTCS
{
	[default] interface ICoPTCS;
};
};

# ----------------------------
# main.cpp (modified from 
http://www.codeproject.com/com/LocalCOMServerClient.asp)
# ----------------------------

#include "../../eclipse_workspace1\PTCS\src\IDL\PTCS.h"    // use your own 
path here
#include "../../eclipse_workspace1\PTCS\src\IDL\PTCS_i.c"  // use your own 
path here
#include "iostream.h"

// for showing possible mistakes
void ShowErrorMessage(LPCTSTR,HRESULT);

int main()
{
   // initialize the COM runtime
   cout << "Initialize the COM runtime...";
   CoInitialize(NULL);
   cout << "success." << endl;

   // declare variables
   HRESULT hr;
   IClassFactory* pICF = NULL;
   ICoPTCS*  pIPTCS = NULL;

   cout << endl << "Get the class factory interface for the PTCS class...";
   hr = CoGetClassObject(CLSID_CoPTCS,CLSCTX_LOCAL_SERVER,		
				// --------- what should I put here? ---------
                         NULL,IID_IClassFactory,(void**)&pICF);
   if ( FAILED(hr) )
   {
      ShowErrorMessage("CoGetClassObject()",hr);
      exit(1);
   }
   else cout << "success." << endl;

   
   cout << "Create the PTCS instance object and get back the IPTCS 
interface...";
   hr = pICF->CreateInstance(NULL,IID_IPTCS,(void**)&pIPTCS);		
			// --------- what should I put here? ---------
   if ( FAILED(hr) )
   {
      ShowErrorMessage("CoCreateInstance()",hr);
      exit(1);
   }
   else cout << "success." << endl;
   if ( pICF )         pICF->Release();
   if ( pIPTCS) pIPTCS->Release();

   cout << endl << "Close the COM runtime...";
   CoUninitialize();
   cout << "success." << endl;
   return 0;

  
}

void ShowErrorMessage(LPCTSTR header, HRESULT hr)
{
   void* pMsg;

   FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
                 FORMAT_MESSAGE_FROM_SYSTEM,NULL,hr,
                 MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), 
                 (LPTSTR)&pMsg,0,NULL);

   cout << header << ": Error(" << hex << hr << "): " 
        << (LPTSTR)pMsg << endl;

   LocalFree(pMsg);
}

---- end of mail







More information about the python-win32 mailing list