Using Smart Pointers

< BACK  NEXT >
[oR]

While it is quite straightforward to create and manage COM component objects using the techniques outlined in the preceding sections, bugs can easily be introduced if the AddRef and Release rules are not strictly followed. To alleviate this problem you can create "smart pointer" classes for interfaces, and these smart pointers automatically call AddRef and Release at the appropriate times.

Smart pointers are created using the _COM_SMARTPTR_TYPEDEF macro that is declared in the header file comdef.h. The macro is passed the following:

  • The class name declaring the interface functions. For example, you may use IPOutlookApp, and this interface is declared in pimstore.h.

  • The result of using the __uuidof macro, which is passed the interface function declaration. This passes the IID (Interface Identifier) to the _COM_ SMARTPTR_TYPEDEF macro.

The following statement will generate a smart interface pointer class called "IPOutlookAppPtr":

 _COM_SMARTPTR_TYPEDEF(IPOutlookApp,       __uuidof(IPOutlookApp)); 

The macro uses the com_ptr_t template class and creates wrapper functions in the new class for each of the interface functions. These wrapper functions perform error checking such as ensuring that the interface pointer is not NULL. For example, the IPOutlookApp interface function "Logon" has the following function generated in the smart pointer class:

 inline HRESULT IPOutlookAppPtr::Logon ( long hWnd ) {   HRESULT _hr = raw_Logon(hWnd);   if (FAILED(_hr)) _com_issue_errorex(_hr, this,       __uuidof(this));   return _hr; } 

These wrapper functions call the "raw" interface functions through the interface's vtable. If the function returns a failure in the HRESULT, the function com_issue_errorex is called, and this in turn calls _com_issue_error. In Windows NT/98/2000, _com_issue_error is implemented in the run-time library, and it generates a C++ exception. In Windows CE you must implement the function you can decide how you want to handle these errors, perhaps by writing to an error log or by notifying the user.

The com_ptr_t template class provides a "CreateInstance" function that allows a component class object to be created. The CreateInstance function is passed a class identifier (CLSID) or a program identifier (ProgID) representing the class to be created. In the following code fragment the variable pOutlookApp is declared using the smart interface class created using com_ptr_t, and CreateInstance is called through that variable. On return from CreateInstance, the pOutlookApp smart pointer wraps an interface pointer to the IPOutlookApp interface.

 IPOutlookAppPtr pOutlookApp; hr = pOutlookApp.CreateInstance(CLSID_Application); 

The code in Listing 14.9 creates a COM component object using CreateInstance, calls the Logon function, obtains the Pocket Output version number, and then calls Logoff. When the function Listing14_9 returns, the variable pOutlookApp's destructor is called, and this calls Release to decrement the interface reference count. As you can see, using smart pointers is easier and safer than coding COM directly.

Listing 14.9 Using smart pointers
 #include <comdef.h> _COM_SMARTPTR_TYPEDEF(IPOutlookApp,         __uuidof(IPOutlookApp)); // Assumes that CoInitializeEx has been called already void Listing14_9(HWND hWnd) {   IPOutlookAppPtr pOutlookApp;   HRESULT hr;   BSTR bstrVersion;   hr = pOutlookApp.CreateInstance(CLSID_Application);   if (FAILED(hr))   {     cout   _T("Could not create object")   endl;     return;   }   hr = pOutlookApp->Logon((long) hWnd);   if (FAILED(hr))     cout   _T("Could not login")   endl;   else   {     pOutlookApp->get_Version(&bstrVersion);     cout   _T("POOM Version: ")            bstrVersion   endl;     pOutlookApp->Logoff();     SysFreeString(bstrVersion);   } } void _com_issue_error(HRESULT hr) {   cout   _T("Error in Smart Pointer access")   endl; } 

Listing 14.9 provides an implementation of _com_issue_error that simply displays an error message. You could raise an exception, write the error to log, or handle the error in another way. Note that an application can only provide a single _com_issue_error function to handle all errors encountered when using com_ptr_t smart pointer classes.

The "#import" compiler directive can also be used to generate smart pointer classes from type library (TLB) files, or from DLL files that contain TLB information. When this technique is used, you do not need to use the _COM_ SMARTPTR_TYPEDEF macro yourself. For example, if your COM component is implemented in MYDLL.DLL, and this DLL contains type library information, you can add the following line to a CPP file to create the smart pointer classes:

 #import "mydll.dll" no_namespace 

The no_namespace attribute specifies that the generated classes will use the global namespace. If this is not included, the classes created by the #import will be created in a namespace whose name is specified in the IDL code used to create the type library information. Using #import is easier than creating _COM_SMARTPTR_TYPEDEF declarations for each interface you intend to use, but many COM objects used with Windows CE do not have suitable type library files. Chapter 16 (ADOCE and SQL Server for Windows CE) shows using #import with type libraries.

The _com_ptr_t template provides other functions for managing COM interfaces, such as the following:

  • AddRef Increments the reference count on an encapsulated COM interface pointer.

  • Release Decrements the reference count on an encapsulated COM interface pointer.

  • Attach This function is passed an interface pointer that the _com_ ptr_t template class then encapsulates.

  • Detach Returns the interface pointer encapsulated by the _com_ptr_t template class. You are responsible for calling Release on the pointer.

  • GetInterfacePtr Returns the encapsulated interface pointer, but the _com_ptr_t template class still maintains responsibility for reference counting.

  • QueryInterface Calls the IUnknown QueryInterface function and returns a raw (non-encapsulated) COM interface pointer.

The Attach function is used quite frequently, since COM interface functions typically return raw, non-encapsulated interface pointers. An example of using Attach is presented in the next section.


< BACK  NEXT >


Windows CE 3. 0 Application Programming
Windows CE 3.0: Application Programming (Prentice Hall Series on Microsoft Technologies)
ISBN: 0130255920
EAN: 2147483647
Year: 2002
Pages: 181

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net