[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