|
|
Title |
How to work with BSTR
|
Summary |
When passing strings to and from COM objects BSTRs are used. This article covers when to allocate, reallocate and free the BSTR. |
Contributor |
Vincent Minden and John McTainsh
|
Published |
6-Feb-2001 |
Last updated |
7-Feb-2001 |
|
|
Description.
Passing strings to and from COM is a very common practice but can be
a little tricky if you don't allocate and deallocate correctly. All
strings are passed as BSTR and can be used with CComBSTR ,
_btr_t and CString under most conditions. The following
should help answer some of the allocation issues associated
with using BSTRs.
What is a BSTR
Some might say that a BSTR is a pointer to an array of wchar_t
, and in part they would be correct. However it is more. It contains the length of
the string so it can contain embedded NULLs. For this reason it must be allocated
using the SysAllocString functions and freed with SysFreeString
.
The simple rules of [in] / [out]
- For [in] type parameters, client allocates and de-allocates the data.
- You may NOT modify BSTRs passed [in] to you.
- For [in,out] type parameters, client allocates, server re-allocates, and
client does a final de-alocation.
- For [out] type parameters including [out,retval] parameters, the server
allocates the data. The client de-allocates output.
Passing BSTR into a function. [in]
Client is responsible for allocating and deallocating the data.
//In COM server implementation
STDMETHODIMP CWhereAmI::SetThing( /*[in]*/BSTR bstrThing )
{
//I do not own it so I cannot modify it.
USES_CONVERSION;
CString sThing = W2T( bstrThing );
return S_OK;
}
...
...
...
//When I am using it
BSTR b1 = SysAllocString( L"Hello" );
pSomeObj->SetThing( b1 );
SysFreeString( b1 );
Getting a BSTR from a function [out] or [out,retval].
Client is responsible for providing and unallocated BSTR which
is populated by the function. The client must then deallocate the data.
//In COM server implementation
STDMETHODIMP CWhereAmI::GetThing( /*[out]*/ BSTR* pbstrThing )
{
//I create BSTR to return.
*pbstrThing = SysAllocString( L"Some returned stuff" );
return S_OK;
}
...
...
...
//When I am using it
BSTR b2 = NULL;
pSomeObj->GetThing( &b2 );
//Use the b2 now...
SysFreeString( b2 );
Getting a BSTR from a function that is passed data in the same BSTR. [in,out]
Client is responsible for allocating the input data and deallocating the output data.
However the server must free and allocate the data to modify. (Or use SysReAllocString )
//In COM server implementation
STDMETHODIMP CWhereAmI::ReverseThing( /*[in,out]*/ BSTR* pbstrThing )
{
USES_CONVERSION;
CString sThing = W2T( *bstrThing );
SysFreeString( *bstrThing );
sThing.MakeReverse();
//I create BSTR to return.
*pbstrThing = sThing.AllocSysString();
return S_OK;
}
...
...
...
//When I am using it
BSTR b3 = SysAllocString( L"Foward Stuff" );
pSomeObj->ReverseThing( &b3 );
//Use the b2 now...
//b3 should now contain "ffutS drawoF"
SysFreeString( b3 );
What else can I use.
Microsoft was kind enough to provide handy classes called CComBSTR and
_btr_t to make handling BSTRs a little simpler. Both classes wrap the BSTR
type to provide useful operators and methods. If you are doing more complex operations
these classes provide a richer set of features.
Credits
I would like to thank Vincent Minden for his help with this article.
Further Reading
A good MSDN article on this topic is
Article 3. Strings the OLE Way
|