Two items:
- Python script that defines and registers a factory COM class and another COM class that can be instantiated by the factory.
- (Ugly) VC++ code that exercises the factory and then the object returned by the factory.
The Python COM object returned by the factory provides rudimentary stemming; ie, it removes any final 's' from a word that is passed to it and returns the truncated word as its result.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | # Python code
from win32com . server . register import UseCommandLine
from win32api import MessageBox
from win32com . client import Dispatch
from win32ui import MessageBox
class StemmerFactory :
_reg_clsid_ = "{602D10EB-426C-4D6F-A4DF-C05572EB780B}"
_reg_desc_ = "LangTech Stemmer"
_reg_progid_ = "LangTech.Stemmer"
_public_methods_ = [ 'new' ]
def new ( self, scriptFile ) :
self . scriptFile = scriptFile
stemmer = Dispatch ( "LangTech.Stemmer.Product" )
return stemmer
class Stemmer :
_reg_clsid_ = "{B306454A-CAE6-4A74-ACAD-0BB11EF256DD}"
_reg_desc_ = "LangTech Stemmer Product"
_reg_progid_ = "LangTech.Stemmer.Product"
_public_methods_ = [ 'stemWord' ]
def stemWord ( self, word ) :
# extremely simple stemming: if the word ends in 's' then drop the 's'
if word [ -1 ] == "s":
return word [ : -1 ]
else:
return word
if __name__ == '__main__' :
UseCommandLine ( StemmerFactory )
UseCommandLine ( Stemmer )
#----------------------------------------
#
# C++
#include <comdef.h>
#include <initguid.h>
DEFINE_GUID(CLSID_StemmerFactory,
0x602D10EB, 0x426C, 0x4D6F, 0xA4, 0xDF, 0xC0, 0x55, 0x72, 0xEB, 0x78, 0x0B);
DISPID rgDispId ;
OLECHAR * rgszNames [ ] = { OLESTR ( "new" ) };
DISPPARAMS DispParams;
VARIANT VarResult;
EXCEPINFO excepinfo;
UINT uArgErr;
VARIANTARG * pvarg = NULL;
_bstr_t stemmedWord;
HRESULT hr;
IDispatch * stemmerFactory;
IDispatch * stemmer;
if ( FAILED ( hr = CoInitialize ( NULL ) ) ) {
MessageBox ( 0, "CoInitialize failure", "Fault", MB_OK );
break;
}
if ( FAILED ( hr = CoCreateInstance (
CLSID_StemmerFactory,
NULL,
CLSCTX_INPROC_SERVER,
IID_IDispatch,
( LPVOID * ) & stemmerFactory ) ) ) {
MessageBox ( 0, "CoCreateInstance failure", "Fault", MB_OK );
break;
}
if ( FAILED ( hr = stemmerFactory -> GetIDsOfNames (
IID_NULL,
rgszNames,
1,
LOCALE_SYSTEM_DEFAULT,
& rgDispId
) ) ) {
MessageBox ( 0, "GetIDsOfNames failure", "Fault", MB_OK );
break;
}
DispParams.cArgs = 1;
DispParams.cNamedArgs = 0;
DispParams.rgdispidNamedArgs = 0;
pvarg = new VARIANTARG [ DispParams . cArgs ];
if ( pvarg == NULL ) {
MessageBox ( 0, "Insufficient 1st memory", "Fault", MB_OK );
break;
}
pvarg -> vt = VT_BSTR;
pvarg -> bstrVal = SysAllocString ( L"engRules.pl" );
DispParams.rgvarg = pvarg;
if ( FAILED ( hr = stemmerFactory -> Invoke (
rgDispId,
IID_NULL,
LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD,
& DispParams,
& VarResult,
& excepinfo,
& uArgErr
) ) ) {
MessageBox ( 0, "1st Invoke failure", "Fault", MB_OK );
break;
}
delete ( pvarg );
stemmer = VarResult.pdispVal;
pvarg = new VARIANTARG [ DispParams . cArgs ];
if ( pvarg == NULL ) {
MessageBox ( 0, "Insufficient 2nd memory", "Fault", MB_OK );
break;
}
pvarg -> vt = VT_BSTR;
pvarg -> bstrVal = SysAllocString ( L"cats" );
DispParams.rgvarg = pvarg;
if ( FAILED ( hr = stemmer -> Invoke (
rgDispId,
IID_NULL,
LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD,
& DispParams,
& VarResult,
& excepinfo,
& uArgErr
) ) ) {
MessageBox ( 0, "2nd Invoke failure", "Fault", MB_OK );
break;
}
delete ( pvarg );
stemmedWord = VarResult.bstrVal;
MessageBox (
0,
( const char * ) stemmedWord,
"Resulting Stemmed Word",
MB_OK
);
CoUninitialize ( );
|
Even moderately able C++ programmers will find my code ugly. (Please feel free to suggest improvements.)
Some tasks are much easier to code in Python (!), and this recipe shows the basics of how to use COM to connect Python to VC++.