from
http://progtutorials.tripod.com/COM.htm
- Definitions of Different Type of Strings
- CString <=> Multibyte String
- CString <=> Wide Character String
- Allocating and Freeing BSTRs with API Functions
- BSTR <=> CString
- BSTR <=> Multibyte String
- Multibyte String <=> Wide Character String
- Converting with ATL Macros
- MFC's BSTR Helper Class _bstr_t
- ATL's BSTR Helper Class CComBSTR
1 Definitions of Different Type of Strings
- wchar_t - In C++ wchar_t is 16-bit wide character represented by unsigned short:
typedef wchar_t WCHAR; // wc, 16-bit UNICODE character
typedef unsigned short wchar_t;
- LPOLESTR - In C++ LPOLESTR is a 16-bit unicode string represented by const unsigned short *:
typedef OLECHAR __RPC_FAR * LPOLESTR;
typedef WCHAR OLECHAR;
- LPCOLESTR - In C++ LPOLESTR is a constant 16-bit unicode string represented by const unsigned short *:
typedef const OLECHAR __RPC_FAR *LPCOLESTR;
- LPSTR - In C++ LPSTR is 8-bit multi-byte/ANSI string represented by char *
typedef CHAR *LPSTR, *PSTR;
typedef char CHAR;
- LPCSTR - In C++ LPCSTR is 8-bit multi-byte/ANSI string represented by const char *:
typedef CONST CHAR *LPCSTR, *PCSTR;
- TCHAR - In C++ TCHAR is 8-bit character represented by char:
typedef char TCHAR, *PTCHAR;
2 CString <=> Multibyte String
#define m(x) ::MessageBox(NULL, x, "Test", MB_OK | MB_TOPMOST)
CString cstr("Hello the world");
// CString::GetBuffer returns a pointer to its underlying buffer.
LPSTR lpsz = cstr.GetBuffer(cstr.GetLength());
// Both lpsz and cstr can access the underlying buffer.
m(lpsz);
m(cstr);
// You can amend the buffer through cstr.
cstr = "Hi Frank.";
m(lpsz);
// You can also amend the buffer through lpsz, but you can't free it.
lpsz[8] = '!';
m(cstr);
// free(lpsz); // Not allowed! Will cause run-time error!
// After releasing the buffer, lpsz's content becomes undefined
cstr.ReleaseBuffer();
m(cstr);
// If you want to avoid amending the original content of the CString,
// make a copy.
LPSTR lpszCopy = (LPSTR)malloc(strlen(lpsz));
memset(lpszCopy, 0, strlen(lpsz) + 1);
strcpy(lpszCopy, lpsz);
m(lpszCopy);
3 CString <=> Wide Character String
void CICPLoginDlg::CStringToWideChar(CString cstr, wchar_t * pwchar, int size)
{
int cstrLen = cstr.GetLength();
ASSERT(cstrLen < MAX_LENGTH);
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, cstr.GetBuffer(cstrLen), cstrLen, pwchar, size);
cstr.ReleaseBuffer();
}
4 Allocating and Freeing BSTRs with API Functions
BSTR stands for basic string. It is a 16-bit Unicode with a prefix telling the count of the bytes in this string, therefore do not need NULL at the end.
When a server creates and passes out a BSTR, the server allocates memory space for the BSTR, while the client should deallocate the memory with a call to API function SysFreeString.
- Creating a new BSTR
BSTR bstr1 = SysAllocString(L"Hello world!");
OLECHAR * pOleStr = OLESTR("Good morning!");
BSTR bstr2 = SysAllocString(pOleStr); - Modifying a BSTR
SysReAllocString(&bstr1, L"Good morning!");
- Freeing a BSTR
SysFreeString(bstr1);
5 BSTR <=> CString
CString cstr(¡°Hello!¡±);
BSTR bstr = cstr.AllocSysString();
BSTR bstr = SysAllocString(L"Hello Frank!");
CString cstr(bstr);
6 BSTR <=> Multibyte String
Second, use function wcstombs (wide character string to multibyte string) and mbstowcs (multibyte string to wide character string):
BSTR bstr1 = SysAllocString(L"Hellow world!");
char * buf[80];
wcstombs(buf, bstr1, 80);
SysFreeString(bstr1);
sprintf(buf, "Good morning!");
BSTR bstr2;
mbstowcs(bstr2, buf, 80);
7 Multibyte String <=> Wide Character String
char * mbstr = "Hello world!";
int len1 = strlen(mbstr);
wchar_t wcbuf[80];
int len2 = sizeof(wcbuf) / sizeof(wchar_t);
::memset(wcbuf, 0, sizeof(wcbuf));
MultiByteToWideChar(
CP_ACP,
MB_PRECOMPOSED,
mbstr,
len1,
wcbuf,
len2);
char buf[300];
sprintf(buf, "wcbuf = %S", wcbuf);
::MessageBox(NULL, buf, NULL, MB_OK);
wchar_t * wcstr = L"Hello world!";
int len3 = wcslen(wcstr);
char mbbuf[300];
int len4 = sizeof(mbbuf);
::memset(mbbuf, 0, len4);
WideCharToMultiByte(
CP_ACP,
WC_COMPOSITECHECK,
wcstr,
len3,
mbbuf,
len4,
NULL,
NULL);
::MessageBox(NULL, mbbuf, NULL, MB_OK);
8 Converting with ATL Macros
ATL provides a group of macros to convert between different types. Because one convertion involves a series of temporary variables to hold and swap the string buffers, the space is prepared by macro USES_CONVERSION, which should be called before any conversion. They are defined in <atlconv.h>.
| ANSI to ... | OLE to ... | TCHAR to ... | wchar_t to ... |
| A2BSTR | OLE2A | T2A | W2A |
| A2COLE | OLE2BSTR | T2BSTR | W2BSTR |
| A2CT | OLE2CA | T2CA | W2CA |
| A2CW | OLE2CT | T2COLE | W2COLE |
| A2OLE | OLE2CW | T2CW | W2CT |
| A2T | OLE2T | T2OLE | W2OLE |
| A2W | OLE2W | T2W | W2T |
USES_CONVERSION;
MessageBox(NULL, W2A(bstr), NULL, MB_OK);
9 MFC's BSTR Helper Class _bstr_t
MFC provides class _bstr_t to wrap BSTR. _bstr_t's constructor can take many types as input:
_bstr_t( ) throw( );
_bstr_t( const _bstr_t & s1 ) throw( );
_bstr_t( const char * s2 ) throw( _com_error );
_bstr_t( const wchar_t * s3 ) throw( _com_error );
_bstr_t( const _variant_t & var ) throw ( _com_error );
_bstr_t( BSTR bstr, bool fCopy ) throw ( _com_error );
Its assignment operator = is also overloaded for many types:
_bstr_t& operator=( const _bstr_t & s1 ) throw ( );
_bstr_t& operator=( const char * s2 ) throw( _com_error );
_bstr_t& operator=( const wchar_t * s3 ) throw( _com_error );
_bstr_t& operator=( const _variant_t & var ) throw( _com_error );
It has also overloaded +=, +, ! and all comparison operators.
To get a LPTSTR from _bstr_t:
_bstr_t bstrt("Hello!");
LPTSTR lp1 = (LPTSTR)bstrt;
LPTSTR lp2 = bstrt.operator char *(); You can use _bstr_t anywhere expecting BSTR. If you like, you can also explicitly cast _bstr_t to BSTR:
_bstr_t bstrt("Hello!");
BSTR bstr = (BSTR)bstrt;
SysFreeString(bstr1); _bstr_t object does not need to be deallocated. It is deallocated automatically when it leaves scope.
Class _bstr_t is contained in header file <comdef.h>.
10 ATL's BSTR Helper Class CComBSTR
ATL also provides a wrapper class CComBSTR, which is more light than _bstr_t. CComBSTR wraps a BSTR data member m_str. Space for BSTR is allocated in its constructor and deallocated in the destructor.
Its constructor can take LPCOLESTR or LPCSTR as input. It can also designate the size of the buffer.
CComBSTR( int nSize );
CComBSTR( int nSize, LPCOLESTR sz );
CComBSTR( int nSize, LPCSTR sz );
CComBSTR( LPCOLESTR pSrc );
CComBSTR( LPCSTR pSrc );
CComBSTR( const CComBSTR& src );
Therefore you can say:
CComBSTR comBstr(¡°Hello!¡±);
To detach m_str from CComBSTR:
BSTR bstr = comBstr.Detach();
To attach a BSTR to a CComBSTR:
BSTR bstr = SysAllocString(L"Hello!");
CComBSTR comBstr;
comBstr.Attach(bstr);
To get a copy of m_str:
BSTR bstr = comBstr.Copy();
To get the address of m_str:
BSTR * pBstr = &comBstr.
To free m_str:
comBstr.Empty();
The overloaded assignment operator takes LPCOLESTR or LPCSTR as parameter. Therefore, to change the value of CComBSTR:
CComBSTR comBstr();
comBstr = L"Good morning!";
CComBSTR can only be casted to CString, which can be than casted to LPCSTR or LPCTSTR:
cstr = (CString)comBstr;
CComBSTR is contained in header file <atlbase.h>, which also contains other wrapper classes.
from
http://progtutorials.tripod.com/COM.htm
SeriousMoin v1 (koMoinMoin 1.0a4 Modified)