BSTR等的相互转换[转]

mac2022-06-30  72

转自  http://www.cppblog.com/lizao2/articles/169250.html   概述   它被描述成一个与自动化相兼容的类型,由于 操作系统提供相应的API函数(如SysAllocString)来管理它以及一些默认的调度代码。因此BSTR实际上就是一个COM字符串,但它却在自动化技术以外的多种场合下得到广泛使用。

为什么需要BSTR

  COM是一种跨编程语言的平台,需要提供语言无关的数据类型。多数编程语言有自己的字符串表示。     ●C++ 字符串是以0结束的ASCII或Unicode字符数组。     ●Visual Basic字符串是一个ASCII字符数组加上表示长度的前缀。     ●Java字符串是以0结束的Unicode字符数组。     需要定义一种通用的字符串类型,可以很容易的匹配到不同编程语言。 在 C++ 中,就是 BSTR。

什么是BSTR

  BSTR是“Basic STRing”的简称, 微软在COM/OLE中定义的标准字符串数据类型。     对于C++,Windows头文件wtypes.h中定义如下:     typedef  wchar_t WCHAR;     typedef WCHAR OLECHAR;     typedef OLECHAR __RPC_FAR *BSTR;;     使用以Null结尾的简单字符串在COM component间传递不太方便。因此, 标准BSTR是一个有长度前缀和null结束符的OLECHAR数组。BSTR的前4字节是一个表示字符串长度的前缀。BSTR长度域的值是字符串的字节数,并且不包括0结束符。     由于是Unicode串,所以字符数是字节数的一半。这种方式的优点是允许程序员在BSTR串中间嵌入NULL字符。但是,BSTR的前四个字节表示长度,而OLECHAR数组的前四字节表示前两个字符。这种情况下,对于C++程序,如何实现BSTR和OLECHAR的交换?答案是COM提供了两个BSTR分配用的API:SysAllocString / SysReallocString。函数返回的指针指向BSTR的第一个字符,而不是BSTR在内存的第一个字节。

什么时候使用BSTR

   只有在你不得不用的时候。      使用BSTR一般有以下几种情况:     ●COM interface接口定义,并且不希望额外提供custom marshaling库(MDIL生成或开发人员自己订制),必须使用BSTR传递字符串。使用C/C++类型的字符串在COM DLL传递字符串,表面上可以使用,但违背了COM的基本规则,并且给以后的扩展留下了隐患。例如,把一个In-process COM Object(简单说COM DLL)改成out-of-process object(COM EXE)。理论上, 客户端的代码应该不做任何改变。但如果是用了C/C++字符串,又希望只使用系统的automation mashaller(Oleaut32.dll),就会出错。     ●如果可以提供custom marshaling,也推荐使用BSTR。     ●客户要求接口必须使用BSTR,和客户讨论后,不能修改。     ●使用的外部库的接口使用BSTR      不使用的情况:     ● 不推荐在IDL结构体中定义BSTR成员,会给结构体的复制和释放带来麻烦。最好直接使用限定最大长度的TCHAR数组。如果确实需要传递变长字符串,BSTR应该被定义成独立的参数或者使用独立的get/set接口。     ● 尽可能缩小的BSTR及相关类型的作用域范围。类的成员变量和函数参数不使用BSTR。 局部变量要尽快释放类的内部不使用BSTR。代码处理逻辑中只在接口直接相关部分使用BSTR。接收到一个BSTR时,尽量立刻变成C/C++的字符串副本进行处理。在需要传递BSTR参数前产生BSTR,用过立即释放。   BSTR、char*和CString转换    (1) char*转换成CString     若将char*转换成CString,除了直接赋值外,还可使用CString::Format进行。例如:   char chArray[] = "This is a test";  char * p = "This is a test";      或   LPSTR p = "This is a test";      或在已定义Unicode应的用程序中   TCHAR * p = _T("This is a test");      或   LPTSTR p = _T("This is a test");  CString theString = chArray;  theString.Format(_T("%s"), chArray);  theString = p;      (2) CString转换成char*     若将CString类转换成char*(LPSTR)类型,常常使用下列三种方法:     方法一,使用强制转换。例如:   CString theString( "This is a test" );  LPTSTR lpsz =(LPTSTR)(LPCTSTR)theString;       方法二,使用strcpy。例如:   CString theString( "This is a test" );  LPTSTR lpsz = new TCHAR[theString.GetLength()+1];  _tcscpy(lpsz, theString);      需要说明的是,strcpy(或可移值Unicode/MBCS的_tcscpy)的第二个参数是 const wchar_t* (Unicode)或const char* (ANSI),系统编译器将会自动对其进行转换。     方法三,使用CString::GetBuffer。例如:   CString s(_T("This is a test "));  LPTSTR p = s.GetBuffer();  // 在这里添加使用p的代码  if(p != NULL) *p = _T('\0');  s.ReleaseBuffer();  // 使用完后及时释放,以便能使用其它的CString成员函数      (3) BSTR转换成char*     方法一,使用ConvertBSTRToString。例如:   #include  #pragma comment(lib, "comsupp.lib")  int _tmain(int argc, _TCHAR* argv[]){  BSTR bstrText = ::SysAllocString(L"Test");  char* lpszText2 = _com_util::ConvertBSTRToString(bstrText);  SysFreeString(bstrText); // 用完释放  delete[] lpszText2;  return 0;  }       方法二,使用_bstr_t的赋值运算符重载。例如:   _bstr_t b = bstrText;  char* lpszText2 = b;      (4) char*转换成BSTR     方法一,使用SysAllocString等API函数。例如:   BSTR bstrText = ::SysAllocString(L"Test");  BSTR bstrText = ::SysAllocStringLen(L"Test",4);  BSTR bstrText = ::SysAllocStringByteLen("Test",4);      方法二,使用COleVariant或_variant_t。例如:   //COleVariant strVar("This is a test");  _variant_t strVar("This is a test");  BSTR bstrText = strVar.bstrVal;      方法三,使用_bstr_t,这是一种最简单的方法。例如:   BSTR bstrText = _bstr_t("This is a test");      方法四,使用CComBSTR。例如:   BSTR bstrText = CComBSTR("This is a test");      或   CComBSTR bstr("This is a test");  BSTR bstrText = bstr.m_str;      方法五,使用ConvertStringToBSTR。例如:   char* lpszText = "Test";  BSTR bstrText = _com_util::ConvertStringToBSTR(lpszText);      (5) CString转换成BSTR     通常是通过使用CStringT::AllocSysString来实现。例如:   CString str("This is a test");  BSTR bstrText = str.AllocSysString();  …  SysFreeString(bstrText); // 用完释放       (6) BSTR转换成CString     一般可按下列方法进行:   BSTR bstrText = ::SysAllocString(L"Test");  CStringA str;  str.Empty();  str = bstrText;       或   CStringA str(bstrText);      (7) ANSI、Unicode和宽字符之间的转换     方法一,使用MultiByteToWideChar将ANSI字符转换成Unicode字符,使用WideCharToMultiByte将Unicode字符转换成ANSI字符。     方法二,使用“_T”将ANSI转换成“一般”类型字符串,使用“L”将ANSI转换成Unicode,而在托管C++环境中还可使用S将ANSI字符串转换成String*对象。例如:   TCHAR tstr[] = _T("this is a test");  wchar_t wszStr[] = L"This is a test";  String* str = S”This is a test”;      方法三,使用ATL 7.0的转换宏和类。ATL7.0在原有3.0基础上完善和增加了许多字符串转换宏以及提供相应的类,它具有如图3所示的统一形式:     其中,第一个C表示“类”,以便于ATL 3.0宏相区别,第二个C表示常量,2表示“to”,EX表示要开辟一定大小的缓冲。SourceType和DestinationType可以是A、T、W和OLE,其含义分别是ANSI、Unicode、“一般”类型和OLE字符串。例如,CA2CT就是将ANSI转换成一般类型的字符串常量。下面是一些示例代码:   LPTSTR tstr= CA2TEX<16>("this is a test");  LPCTSTR tcstr= CA2CT("this is a test");  wchar_t wszStr[] = L"This is a test";  char* chstr = CW2A(wszStr);       六、结语     几乎所有的程序都要用到字符串,而Visual C++.NET由于功能强大、应用广泛,因而字符串之间的转换更为频繁。本文几乎涉及到目前的所有转换方法。当然对于.NET框架来说,还可使用Convert和Text类进行不同数据类型以及字符编码之间的相互转换。  

转载于:https://www.cnblogs.com/Dennis-mi/articles/3456997.html

相关资源:JAVA上百实例源码以及开源项目
最新回复(0)