ysString(BSTR*)
这两个函数提供了串与BSTR的转换。使用时须注意一点:当调用AllocSysString()后,
须调用它SysFreeString(...) ,例:
CString sBuf="TestCString";
BSTR bsBuf=sBuf.AllocSysString();
::SysFreeString(bsBuf);
bsBuf=::SysAllocString(L"Hi,I'm BSTR");
sBuf=bsBuf;
TRACE(_T("%s\n"),sBuf);
::SysFreeString(bsBuf);
2. COM 中的字符串BSTR和VARIANT
2.1. BSTR字符串类型
很多自动化和COM接口使用BSTR来定义字符串。BSTR 是 Pascal-style 字符串(字符串长度被明确指出)和C-style字符串(字符串的长度要通过寻找结束符来计算)的混合产物。一个BSTR是一个Unicode字符串,它的长度是预先考虑的,并且它还有一个0字符作为结束标记。下面是一个BSTR的示例:06 00 00 00 42 00 6F 00 62 00 00 00
--length-- B o b EOS
注意字符串的长度是如何被加到字符串数据中的。长度是DWORD类型的,保存了字符串中包含的字节数,但不包括结束标记。在这个例子中,"Bob"包含3个Unicode字符(不包括结束符),总共6个字节。字符串的长度被预先存储好,以便当一个BSTR在进程或者计算机之间被传递时,COM库知道多少数据需要传送。(另一方面,一个BSTR能够存储任意数据块,而不仅仅是字符,它还可以包含嵌入在数据中的0字符。)。
在 C++ 中,一个 BSTR 实际上就是一个指向Unicode字符串中第一个字符的指针。它的定义如下:
BSTR bstr = NULL;
bstr = SysAllocString ( L"Hi Bob!" );
if ( NULL == bstr )
// out of memory error
// Use bstr here...
SysFreeString ( bstr );
另外一个用在自动化接口中的变量类型是VARIANT。它被用来在无类型(typeless)语言,如Jscript和VBScript,来传递数据。一个VARIANT可能含有很多不同类型的数据,例如long和IDispatch*。当一个VARIANT包含一个字符串,字符串被存成一个BSTR。后面讲到VARIANT封装类时,会对VARIANT多些介绍。
2.2. BSTR的包装类_bstr_t
_bstr_t是一个对BSTR的完整封装类,实际上它隐藏了底层的BSTR。它提供各种构造函数和操作符来访问底层的C语言风格的字符串。然而,_bstr_t却没有访问BSTR本身的操作符,所以一个_bstr_t类型的字符串不能被作为输出参数传给一个COM方法。如果你需要一个BSTR*参数,使用ATL类CComBSTR是比较容易的方式。
一个_bstr_t字符串能够传给一个接收参数类型为BSTR的函数,只是因为下列3个条件同时满足。首先,_bstr_t有一个向wchar_t*转换的转换函数;其次,对编译器而言,因为BSTR的定义,wchar_t*和BSTR有同样的含义;第三,_bstr_t内部含有的wchar_t*指向一片按BSTR的形式存储数据的内存。所以,即使没有文档说明,_bstr_t可以转换成BSTR,这种转换仍然可以正常进行。
// Constructing
void Test_bstr_t()
{
_bstr_t bs1 = "char string"; // construct from a LPCSTR
_bstr_t bs2 = L"wide char string"; // construct from a LPCWSTR
_bstr_t bs3 = bs1; // copy from another _bstr_t
_variant_t v = "Bob";
_bstr_t bs4 = v; // construct from a _variant_t that has a string
// Extracting data
LPCSTR psz1 = bs1; // automatically converts to MBCS string
LPCSTR psz2 = (LPCSTR) bs1; // cast OK, same as previous line
LPCWSTR pwsz1 = bs1; // returns the internal Unicode string
LPCWSTR pwsz2 = (LPCWSTR) bs1; // cast OK, same as previous line
BSTR bstr = bs1.copy(); // copies bs1, returns it as a BSTR
// ...
SysFreeString ( bstr );
}
注意_bstr_t也提供char*和wchar_t*之间的转换操作符。但不提倡使用,因为即使它们是非常量字符串指针,你也一定不能使用这些指针去修改它们指向的缓冲区的内容,因为那将破坏内部的BSTR结构。
2.3. _variant_t
_variant_t是一个对VARIANT的完整封装,它提供很多构造函数和转换函数来操作一个VARIANT可能包含的大量的数据类型。这里,介绍与字符串有关的操作。
void TestVariant()
{
_variant_t v1 = "char string"; // construct from a LPCSTR
_variant_t v2 = L"wide char string"; // construct from a LPCWSTR
_bstr_t bs1 = "Bob";
_variant_t v3 = bs1; // copy from a _bstr_t object
// Extracting data
_bstr_t bs2 = v1; // extract BSTR from the VARIANT
_bstr_t bs3 = (_bstr_t) v1; // cast OK, same as previous line
}
注意:
如果类型转换不能被执行,_variant_t方法能够抛出异常,所以应该准备捕获_com_error异常。
还需要注意的是:
没有从一个_variant_t变量到一个MBCS