COM的基本字符串类型:OLECHAR和Basic String (BSTR)。
一、从OLECHAR开始
OLECHAR(定义在<wtypes.h>
)是C++里的标准COM字符数据类型。COM组件中有很大一部分方法希望他们的接受的字符串参数是OLECHAR数组。
OLECHAR会根据你的目标运行平台转换为char (ANSI) 或wchar_t (Unicode)字符。详见理解OLECHAR
二、BSTR、_bstr_t与CComBSTR
BSTR是带有字符串长度信息的以NULL结尾的一个OLECHAR数组。
BSTR是32位指针。LP表示长指针,在win16下有长指针(LP)和短指针(P)的区别,而在win32下是没有区别的,都是32位,所以LP和P是等价的
typedef OLECHAR *BSTR;//<wtypes.h>
CComBSTR是COM对BSTR的封装。它不需要手动去管理BSTR字符串的申请和释放。
_bstr_t是C++对BSTR的封装
参考COM中的OLECHAR ,BSTR和CComBSTR的理解和应用
三、CString和LPCTSTR
CString是一个动态TCHAR数组,BSTR是一种专有格式的字符串(需要用系统提供的函数来操纵,见上文),LPCTSTR只是一个常量的TCHAR指针。
3.1 先要了解一下TCHAR
为了了解TCHAR,则还要先了解ANSI和Unicode标准。ANSI, UNICODE,UTF8编码的区别
还要了解一下LPSTR与LPCSTR:
vc++中各种字符串的表示法
首先char* 是指向ANSI字符数组的指针,其中每个字符占据8位(有效数据是除掉最高位的其他7位),这里保持了与传统的C,C++的兼容。
LP的含义是长指针(long pointer)。LPSTR是一个指向以‘\0’结尾的ANSI字符数组的指针,与char*可以互换使用,在win32中较多地使用LPSTR。
而LPCSTR中增加的‘C’的含义是“CONSTANT”(常量),表明这种数据类型的实例不能被使用它的API函数改变,除此之外,它与LPSTR是等同的。
总结:
1.LP表示长指针,在win16下有长指针(LP)和短指针(P)的区别,而在win32下是没有区别的,都是32位.所以这里的LP和P是等价的.
2.C表示const
为了满足程序代码国际化的需要,业界推出了Unicode标准,它提供了一种简单和一致的表达字符串的方法,所有字符都是16位的双字节值;
其数量也可以满足差不多世界上所有书面语言字符的编码需求,开发程序时使用Unicode(类型为wchar_t)是一种被鼓励的做法。
由此产生了LPWSTR与LPCWSTR,它们的含义类似于LPSTR与LPCSTR,只是字符数据是16位的wchar_t而不是char。
然后为了实现两种编码的通用,提出了TCHAR的定义:
如果定义_UNICODE,声明如下:
typedef wchar_t TCHAR;
如果没有定义_UNICODE,则声明如下:
typedef char TCHAR;
也就是说,TCHAR实际上就是一个宏定义。T前缀表示,在采用Unicode方式编译时是wchar_t,在普通时编译成char.(类似地,LPTSTR和LPCTSTR中T的含义就是每个字符是这样的TCHAR。)
LPCTSTR:
#ifdef _UNICODE
typedef const wchar_t * LPCTSTR;
#else
typedef const char * LPCTSTR;
#endif
3.2 CString
CString类中的字符就是被声明为TCHAR类型的,它提供了一个封装好的类供用户方便地使用。
CString类还封装了很多方法,重载了支持很多类型字符串格式的构造函数和运算符
3.2.1 CString、CStringA 和 CStringW
Visual C++.NET中将CStringT作为ATL和MFC的共享的“一般”字符串类,它有CString、CStringA和CStringW三种形式,分别操作不同字符类型的字符串。这些字符类型是TCHAR、char和wchar_t。
TCHAR在Unicode平台中等同于WCHAR(16位 Unicode字符),在ANSI中等价于char。
wchar_t通常定义为unsigned short。由于CString在MFC应用程序中经常用到,这里不再重复。
四、VARIANT、COleVariant 和_variant_t
在OLE、ActiveX和COM中,VARIANT数据类型提供了一种非常有效的机制,由于它既包含了数据本身,也包含了数据的类型,因而它可以实现各种不同的自动化数据的传输。
下面让我们来看看OAIDL.H文件中VARIANT定义的一个简化版:
struct tagVARIANT {
VARTYPE vt;
union {
short iVal; // VT_I2.
long lVal; // VT_I4.
float fltVal; // VT_R4.
double dblVal; // VT_R8.
DATE date; // VT_DATE.
BSTR bstrVal; // VT_BSTR.
…
short * piVal; // VT_BYREF|VT_I2.
long * plVal; // VT_BYREF|VT_I4.
float * pfltVal; // VT_BYREF|VT_R4.
double * pdblVal; // VT_BYREF|VT_R8.
DATE * pdate; // VT_BYREF|VT_DATE.
BSTR * pbstrVal; // VT_BYREF|VT_BSTR.
};
};
显然,VARIANT类型是一个C结构,它包含了一个类型成员vt、一些保留字节以及一个大的union类型。
例如,如果vt为VT_I2,那么我们可以从iVal中读出VARIANT的值。
同样,当给一个VARIANT变量赋值时,也要先指明其类型。例如:
VARIANT va;
:: VariantInit(&va); // 初始化
int a = 2002;
va.vt = VT_I4; // 指明long数据类型
va.lVal = a; // 赋值
为了方便处理VARIANT类型的变量,Windows还提供了这样一些非常有用的函数:
VariantInit —— 将变量初始化为VT_EMPTY;
VariantClear —— 消除并初始化VARIANT;
VariantChangeType —— 改变VARIANT的类型;
VariantCopy —— 释放与目标VARIANT相连的内存并复制源VARIANT。
COleVariant类是对VARIANT结构的封装。
它的构造函数具有极为强大大的功能,当对象构造时首先调用VariantInit进行初始化,然后根据参数中的标准类型调用相应的构造函数,并使用VariantCopy进行转换赋值操作;当VARIANT对象不在有效范围时,它的析构函数就会被自动调用,由于析构函数调用了VariantClear,因而相应的内存就会被自动清除。
除此之外,COleVariant的赋值操作符在与 VARIANT类型转换中为我们提供极大的方便。例如下面的代码:
COleVariant v1(”This is a test”); // 直接构造
COleVariant v2 = “This is a test”;
// 结果是VT_BSTR类型,值为”This is a test”
COleVariant v3((long)2002);
COleVariant v4 = (long)2002;
// 结果是VT_I4类型,值为2002
_variant_t是一个用于COM的VARIANT类,它的功能与COleVariant相似。不过在Visual C++.NET的MFC应用程序中使用时需要在代码文件前面添加下列两句:
#include “comutil.h”
#pragma comment( lib, “comsupp.lib” )
五、相互转换
各种类型格式的转换可以参考这篇文章。
里面也是copy了三篇文章,很全(但是脉络不太清晰)。