JAL Computing
|
Using CComBSTRThe concept of strings (Unicode, ANSI, MBCS) is discussed in "ATL Internals" and "Article 3. Strings the OLE Way" listed in the references page. A BSTR is simply a typedef:
However, a BSTR must adhere to a very specific set of rules that differs from a LPWSTR:
Internally, the BSTR string is length prefixed, null terminated and may contain nulls within the body of the string. A null BSTR is interpreted as representing an empty string. Externally, the BSTR is allocated to the system heap using SysAllocString so that a BSTR can be passed between processes such as a COM component and an ASP script. Once allocated, you cannot change the size of the string and you can only modify a string if you own the string. To avoid a memory leak, the owner of the string must deallocate the BSTR appropriately, ultimately by calling SysFreeString. The rules of string ownership are documented in the article "Strings the OLE Way." In a nutshell, you own a BSTR that is returned to you by reference as an [out, retval] BSTR *pVal. You do not own a BSTR passed to you by value as [in] BSTR newVal. You can, however, copy a BSTR passed in by value. To return a BSTR by reference, you must create the BSTR, allocating memory for the string on the system heap. You should not free a BSTR that you plan to return by reference as an [out,retval]. It is up to the calling client to free the BSTR. This is similar to calling new() in the COM dll method and delete() in the client script. CComBSTR is an ATL wrapper class that greatly simplifies the construction and management of BSTRs, automating the creation of BSTRs in the constructor and assignment operator and automating the release of BSTRs in the destructor. It provides methods Detach and CopyTo which can be used to return a BSTR by reference as an [out, retval]. Although CComBSTR does not provide high level string manipulation functions, CComBSTR can be used in conjunction with the <string> library. Alternatively, you can use low level access to the contained string using the m_str property and pointer arithmetic. Finally, there are ATL MACROS that automate conversions between the various types of strings.
CComBSTR Automates Memory Allocation/DeallocationHere is a do nothing verbose method that creates and releases a BSTR:
CComBSTR automates memory allocation/deallocation as is apparent by the following version of DoNothing:
Memory for the BSTR is allocated in the CComBSTR constructor. When the CComBSTR object goes out of scope, the string memory is released in the CComBSTR destructor. When to use Detach() vs CopyTo(pVal)If you want to return a BSTR by reference as an [out,retval] you must construct the BSTR by allocating memory on the system heap. Although CComBSTR simplifies the construction and management of BSTRs, you must not return a CComBSTR as an [out,retval] by reference. If you return a local CComBSTR object, when the object goes out of scope, the BSTR will be released in the CComBSTR destructor and the client script will have a BSTR pointer to released memory. This is analogous to mistakenly returning a reference to a local object. Moreover, if you return a member CComBSTR object, then there may be more than one BSTR pointer to the same string memory location and the BSTR in memory will be released when the member CComBSTR object goes out of scope. An overly simplistic approach to this problem is to always use CopyTo(pVal) when returning a CComBSTR by reference as an [out,retval].
However, if CComBSTR is a local object, as in the above code snippet, this is inefficient calling SysAllocString twice, once in the constructor and once in CopyTo. Instead the general rule should be to use Detach() when returning a local CComBSTR by reference as an [out, retval]. Use CopyTo(pVal) when returning a member CComBSTR by reference as an [out, retval]. The following code snippets demonstrate this rule:
The Detach() method clears the CComBSTR without releasing the BSTR from memory. As a result, there is no BSTR to be release when the CComBSTR object goes out of scope. Using the <string> Library with CComBSTRAlthough CComBSTR does not provide high level string manipulation routines, you can manipulate strings using the <string> library. You will need to add #include <string> to the header file. You can convert a CComBSTR to a wstring like this:
You can convert a wstring to a CComBSTR object like this:
The following code snippet parses a BSTR of comma separated tokens and returns the number of tokens found. It has been adapted from Shelley Powers "Developing ASP Components Second Edition".
You can convert the wstring strToken to a _variant_t like this:
Low Level Access to m_strIt is also possible to access a BSTR using the encapsulated m_str. The m_str can be traversed using pointer arithmetic... not for the faint of heart. The following code snippet demonstrates low level read only access to the contained string. Remember, you should not change the size of the contained string and you can only change the contents of the contained string if you own the string. The following code snippet replaces double quotes in a string with the HTML " for proper display in an HTML FORM:
The CComBSTR strTemp now contains the "new" string. For fun, here is the <string> version with appreciation for the folks at Compuserve's Developer Application forum:
ATL String Conversion MacrosAt times you may need to convert among the ANSI (A), Unicode (W) or OLE (T) string types. The ATL provides a large number of MACROS that will do this for you including: A2W
LPSTR --> LPWSTR You must add the line: USES_CONVERSION; as the first executable statement in the function to enable the ATL string macros. Be aware that the BSTR macros (A2BSTR, T2BSTR, OLE2BSTR) allocate memory on the system heap when converting to the type BSTR. You are still responsible for managing these BSTRs on the system heap. I have found the A2W macro the useful for converting long values to a CComBSTR. The following code snippet demonstrates the use of ltoa(), A2W, and CComBSTR to return a BSTR as an [out, retval] by reference.
Have fun, |
Send mail to [email protected]
with questions or comments about this web site. Copyright © 2001, 2002, 2003,
2004, 2005, 2006, 2007, 2008, 2009 ©
|