As discussed in Chapter 14 (COM and ActiveX), COM components are accessed most easily through smart pointer class templates. In Chapter 14 smart pointers were created using _COM_SMARTPTR_TYPEDEF after header (.h) files were used that included the interface definitions. An alternate, and sometimes easier, approach is to import a type library (TLB) file that includes all the interface definitions. The #import will generate smart pointer class templates for each interface contained in the TLB file. You can create a TLB from the IDL files with the Microsoft Interface Definition Language compiler (MIDL.EXE). This is distributed with Microsoft Visual Studio and eMbedded Visual C++. You will need two TLB files for accessing databases ADOCE31.TLB and ADOXCE31.TLB. These TLB files may not be distributed with your development tool, so for your convenience copies have been placed on the CDROM in the directory \examples. If you need to build them from IDL files, enter the command "midl.exe adoce31.idl" in the folder where the IDL files are located (typically the relevant "include" folder). You will need to ensure that the following IDL files are available for inclusion: oaidl.idl, objidl.idl, ocidl.idl, oleidl.idl, unknwn.idl, and wtypes.idl. Two #import statements are required, one for each of the TLB files. Names in these TLB files may well clash with names used elsewhere, such as in other header files. Therefore, the namespace for each #import is changed using the rename_namespace attribute. In the code for this chapter, the namespace for ADOCE is "AdoNS" and for ADOXCE is "AdoXNS". Even when using these namespaces, the EOF name used in ADO still clashes, and so this is renamed to "A_EOF". This means that the ADOCE method called "GetEOF" now needs to be referred to as "GetA_EOF". You will also need to do the following:
Here, then, is the code you will need to include before using smart pointer classes for ADOCE: #include <comdef.h> _COM_SMARTPTR_TYPEDEF(IUnknown, __uuidof(IUnknown)); #import "adoce31.tlb" rename ("EOF", "A_EOF") rename_namespace ("AdoNS") #import "adoxce31.tlb" rename_namespace ("AdoXNS") void _com_issue_errorex(HRESULT hr, IUnknown* pUnkn, REFIID riid) { cout _T("COM Error: ") hr endl; } The #import statements will result in .tlh (header) and .tli (implementation) files being created for ADOCE and ADOXCE. These files will be placed in the output directory for the build (for example, "sh3dbg"). It is well worth looking at these files to determine the precise implementation of the methods and properties, since smart pointers change the return types and parameters for methods and properties. The _com_issue_errorex function is called by the smart pointer functions that wrap the interface functions when an HRESULT returns a failure. Many of the smart pointer functions that would usually return an HRESULT return a value that would normally be returned as an out parameter. This makes them easier to call, but means that the HRESULT cannot be tested. Therefore, you should have _com_issue_errorex raise an exception or report the error in some way. In the sample above the value in the offending HRESULT is just displayed. Table 16.1 shows the smart pointer interface classes created by these imports together with the namespace for each of the classes.
|