VII.1.1.4 Using component with C++
The example is provided in the following files:
- “COMEX/EX01/testClaCom.cpp” is the principal file containing calculation functions
and the main program.
- “COMEX/EX01/util.cpp” contains the definition of utility functions. (Mainly conversion
functions.)
- “COMEX/EX01/util.h” contains the declarations of the same functions.
The batch file “COMEX/EX01/build.bat” is used to compile the example. The compilation messages
should look as follows:
g++ -c testClaCom.cpp -I"H:' OUTPUTS' COM' include"
g++ -c util.cpp
g++ -o testClaCom.exe testClaCom.o util.o '
"H:' OUTPUTS' COM' lib' FeresPost.dll" -lole32 -loleaut32 '
-luuid -lstdc++
(You may have to change the compilation commands, options and files access to compile the program
on your computer.)
In a C++ program, several headers must first be included in the program to have access to classes,
methods and GUIDs declarations and/or definitions:
#include <Application.hxx>
#include <Application_i.c>
#include <ClaDb.hxx>
#include <ClaLam.hxx>
#include <ClaMat.hxx>
#include <ClaLoad.hxx>
#include <IterX.hxx>
#include <Iterator.hxx>
(The included files are distributed with the FeResPost COM library in the “include” directory.) The
access to the component and the initialization is done as follow:
if (!CoInitialize(0)){
if ((hr = CoGetClassObject(CLSID_Application, CLSCTX_INPROC_SERVER,
0, IID_IClassFactory, (LPVOID *)&classFactory))) {
MessageBox(0, "Can’t get IClassFactory", "CoGetClassObject error",
MB_OK|MB_ICONEXCLAMATION);
cerr << hr << endl ;
exit(-1);
}
else {
if ((hr = classFactory->CreateInstance(0, IID_IApplication,
(LPVOID *)&frpApp))) {
classFactory->Release();
MessageBox(0, "Can’t create IApplication object",
"CreateInstance error",MB_OK|MB_ICONEXCLAMATION);
return -1;
}
else {
classFactory->Release();
MessageBox(0, "SUCCESS", "SUCCESS", MB_OK|MB_ICONEXCLAMATION);
}
}
}
frpApp->newObject(BSTR_ClaDb,(IDispatch**)&db);
string2variant("test.ndf",fileName);
db->readNeutral(fileName);
As you can see, it is a little more complicated than in ruby or python.
The entire C++ example shows that it is significantly more complicated to use COM component
with compiled languages than with interpreted languages that support COM automation. This is
related to several factors:
Just to illustrate the points above, one gives below an example of the programming lines necessary to
perform the iterations on laminate and load IDs and call the calculation functions:
VARIANT lamId,loadId;
IIterator *lamIt,*loadIt;
IIterX *lamIterX,*loadIterX;
ULONG pCeltFetched;
...
db->get_iter_laminateId((IDispatch**)&lamIt);
lamIt->get_newEnum((IUnknown**)&lamIterX);
db->get_iter_loadId((IDispatch**)&loadIt);
loadIt->get_newEnum((IUnknown**)&loadIterX);
lamIterX->Reset();
for (lamIterX->Next(1,&lamId,&pCeltFetched);pCeltFetched>0;
lamIterX->Next(1,&lamId,&pCeltFetched)) {
printLamProperties(db,os,lamId);
loadIterX->Reset();
for (loadIterX->Next(1,&loadId,&pCeltFetched);pCeltFetched>0;
loadIterX->Next(1,&loadId,&pCeltFetched)) {
printLoadResponse(db,os,lamId,loadId,0.0,criteria);
}
}
lamIterX->Release();
lamIt->Release();
loadIterX->Release();
loadIt->Release();
Actually, the example shows that the component that is being developed is adapted to the use with
languages that support the Microsoft IDispatch interface. However, a library adapted to the use with
C++ language should also be developed. Consequently we do not advise to use the component from
C++ or C language.