BSTR是COM中默认的字符串数据格式,和char* 及std::string等不同,BSTR is a null-terminated, length-prefixed, unicode string.
下面是一个非常好的对BSTR的解释: A bstr is a pointer to a string of wide char. The string is not terminated. Instead, the length of the string is stored as an unsigned long just before the first character of the string. (这一点和普通的 *char很不同,因为*char 指针指向的是该串的第一个字符,而bstr的指针是指向该字符串的长度) You might think that you could create a bstr the c++ way, by creating a structure and then returning a pointer to the second element, cast to bstr, but you should never do this! the memory pointed to by a bstr is actually owned by Windows. Becaust a bstr's memory is owned by Windows, you can safely pass a bstr between processes. Instead, you can use the function SysAllocString() to create a bstr, and the function SysFreeString() to destroy it properly. In fact, you should only use platform SDK functions (or helper classes that use them internally) to manipulate bstrs.
缺点: most of the string manipulation functions normaly taken for granted, such as finding a substring, comparing two strings, and so on, are missing. Most significantly, there seems to be no function to copy a bstr.
CComBSTR: 是ATL中的一个类, this class is wrapper for BSTR,
_bstr_t: 是BSTR的封装类,实际上是一个smart pointer, it encapsulates the BSTR date type. It manages resource allocation and deallocation through function calls to SysAllocString / SysFreeString and other BSTR APIs. _bstr_t 其实相当于一个带有引用计数的智能指针。
_bstr_t: is "native COM support" class. And CComBSTR is the ATL class. the two classes are very similar. Both will take care of allocating and deallocating the wrapped bstr in the class constructor and destructor. They also can be used to take charge of an existing bstr with the Attach() method, or can be made to abandon the bstr with Detach() method. The have helpful operators and methods to compare two string, copy a string, and so on. In many cases, _bstr_t and CComBSTR instances can be passed as bstr substitues. ( 但要注意:有时候不恰当的使用这两个类来代替bstr有可能会造成内存泄露)
CComBSTR和 _bstr_t 都是BSTR的wrapper,但实现机制不同, _bstr_t更通用些,不过如果使用ATL的话,可能 CComBSTR更方便些。
------------------------------------------------------------------------
CComBSTR是封装了BSTR的一个类。
CComBSTR提供了A构造函数、B赋值操作、C获得内部BSTR方法、D连接、E大小写转换操作、F比较操作、G永久性操作等。CComBSTR提供了8个构造函数、3个赋值操作方法、4个和内部BSTR有关的方法、9个连接方法、2个大小写转换方法、5个比较操作方法、2个永久性操作方法(写入和读取)。
Attention:Make sure that you have included the altbase.h file in your project.
即在头文件中有#include<altbase.h>
否则会在程序编译时会报错:error C2065: 'CComBSTR' : undeclared identifier
相关代码操作说明我在如下代码里进行了注释:
//A.CComBSTR的8个构造函数
//1.默认构造函数,把m_str初始化为NUL
CComBSTR cbstr1;
LPCOLESTR myOleStr = L"Hello const OLE string";
//使用OLESTR宏可以获得正确的参数类型
LPCOLESTR myOleStrMacro = OLESTR("construct a correct string by olestr macro");
//2.常用构造函数,已NUL结尾的OLESTR构造
CComBSTR cbstr2(myOleStr);
//3.指定缓冲长度,不包括NUL结尾字符
CComBSTR cbstr3(64,myOleStr);
//4.指定缓冲长度n,并补足n个NUL
CComBSTR cbstr4(64);
//5.拷贝构造函数
CComBSTR cbstr5(cbstr4);
LPCSTR myCStr = "Hello const c string";
//6.使用C string构造CComBSTR
CComBSTR cbstr6(myCStr);
//7.使用C string构造指定长度n字符串,以NUL补足长度n
CComBSTR cbstr7(64,myCStr);
//8.把c风格的IID转换为字符串形式({...}形式)
CComBSTR cbstr8(IID_IUnknown);
//B.CComBSTR的3个赋值操作
//1.CComBSTR之间的operator=
cbstr8 = cbstr7;
//2.使用LPCOLESTR赋值
cbstr8 = myOleStr;
//3.使用LPCSTR赋值
cbstr8 = myCStr;
//C.4个获得内部BSTR的方法
//1.operator BSTR() const {return m_str;}
//注意如果使用取址(&)获得BSTR,我们并没有控制权,它还是归CComBSTR管理
BSTR myInnerBSTR = (BSTR)cbstr8;
//2.使用CopyTo获得内部BSTR的拷贝,我们完全拥用了BSTR的所有权,要自己负责释放
BSTR myCopyBSTR;
cbstr8.CopyTo(&myCopyBSTR);
//3.使用Detach方法,CComBSTR内部的BSTR将被释放
BSTR myDetachBSTR = cbstr8.Detach();
//4.Attach方法,把我们拥有所有权的BSTR交给CComBSTR管理
BSTR myAttachBSTR = SysAllocString(L"hello bstr");
cbstr8.Attach(myAttachBSTR);
//D.CComBSTR的连接
//1.连接上指定长度缓冲,并附加给定的LPCOLESTR
cbstr8.Append(myOleStr,32);
//2.连接给定的LPCOLESTR
cbstr8.Append(myOleStr);
//3.连接c string
cbstr8.Append(myCStr);
//4.连接一个c字符
cbstr8.Append('x');
//5.连接一个wchar_t
wchar_t wc = '测';
cbstr8.Append(wc);
//6.连接一个CComBSTR
cbstr8.Append(cbstr7);
//7.使用operator+连接CComBSTR
cbstr8 += cbstr7;
//8.连接BSTR
cbstr8.Append(myInnerBSTR);
//9连接给定的cstring
cbstr8.AppendBytes("hello world",32);
//E.大小写转换
cbstr8.ToLower();
cbstr8.ToUpper();
//F.比较操作
//1.NUL检查
if(!cbstr8)
{
//非空
}
//2.CComBSTR之间的比较
if (cbstr8 < cbstr7)
{
}
//3.CComBSTR和LPCSTR之间的比较
if (cbstr8 < myCStr)
{
}
//4.CComBSTR和LPCOLESTR之间的比较
if (cbstr8 < myOleStr)
{
}
//5.CComBSTR和LPOLESTR之间的比较
LPOLESTR myUncOleStr = L"hello ole str";
if (cbstr8 < myUncOleStr)
{
}
//G.永久性
IStream* istrm = NULL;
//1.写入流操作
cbstr8.WriteToStream(istrm);
//2.从流中读取操作
cbstr8.ReadFromStream(istrm);