
| API 函数 | 说明 | 
| SysAllocString() | 申请一个 BSTR 指针,并初始化为一个字符串 | 
| SysFreeString() | 释放 BSTR 内存 | 
| SysAllocStringLen() | 申请一个指定字符长度的 BSTR 指针,并初始化为一个字符串 | 
| SysAllocStringByteLen() | 申请一个指定字节长度的 BSTR 指针,并初始化为一个字符串 | 
| SysReAllocStringLen() | 重新申请 BSTR 指针 | 
| CString 函数 | 说明 | 
| AllocSysString() | 从 CString 得到 BSTR | 
| SetSysString() | 重新申请 BSTR 指针,并复制到 CString 中 | 
| CComBSTR 函数 ATL 的 BSTR 包装类。在 atlbase.h 中定义 | |
| Append()、AppendBSTR()、AppendBytes()、ArrayToBSTR()、BSTRToArray()、AssignBSTR()、Attach()、Detach()、Copy()、CopyTo()、Empty()、Length()、ByteLength()、ReadFromStream()、WriteToStream()、LoadString()、ToLower()、ToUpper() 运算符重载:!,!=,==,<,>,&,+=,+,=,BSTR | 太多了,但从函数名称不能看出其基本功能。详细资料,查看MSDN 吧。另外,左侧函数,有很多是 ATL 7.0 提供的,VC6.0 下所带的 ATL 3.0 不支持。 由于我们将来主要用 ATL 开发组件程序,因此使用 ATL 的 CComBSTR 为主。VC也提供了其它的包装类 _bstr_t。 | 
| 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 | 
C++、BASIC、Java、Pascal、Script......计算机语言多种多样,而它们各自又都有自己的数据类型,COM 产生目的,其中之一就是要跨语言(注3)。而 VARIANT 数据类型就具有跨语言的特性,同时它可以表示(存储)任意类型的数据。从C语言的角度来讲,VARIANT 其实是一个结构,结构中用一个域(vt)表示------该变量到底表示的是什么类型数据,同时真正的数据则存贮在 union 空间中。结构的定义太长了(虽然长,但其实很简单)大家去看 MSDN 的描述吧,这里给出如何使用的简单示例:
学生:我想用 VARIANT 表示一个4字节长的整数,如何做?
老师:VARIANT v; v.vt=VT_I4; v.lVal=100;
学生:我想用 VARIANT 表示布尔值“真”,如何做?
老师:VARIANT v; v.vt=VT_BOOL; v.boolVal=VARIANT_TRUE;
学生:这么麻烦?我能不能 v.boolVal=true; 这样写?
老师:不可以!因为
| 类型 | 字节长度 | 假值 | 真值 | 
| bool | 1(char) | 0(false) | 1(true) | 
| BOOL | 4(int) | 0(FALSE) | 1(TRUE) | 
| VT_BOOL | 2(short int) | 0(VARIANT_FALSE) | -1(VARIANT_TRUE) | 
  所以如果你 v.boolVal=true 这样赋值,那么将来 if(VARIANT_TRUE==v.boolVal) 的时候会出问题(-1 != 1)。但是你注意观察,任何布尔类型的“假”都是0,因此作为一个好习惯,在做布尔判断的时候,不要和“真值”相比较,而要与“假值”做比较。
学生:谢谢老师,你太牛了。我对老师的敬仰如滔滔江水,连绵不绝......
学生:我想用 VARIANT 保存字符串,如何做?
老师:VARIANT v; v.vt=VT_BSTR; v.bstrVal=SysAllocString(L"Hello,你好");
学生:哦......我明白了。可是这么操作真够麻烦的,有没有简单一些的方法?
老师:有呀,你可以使用现成的包装类 CComVariant、COleVariant、_variant_t。比如上面三个问题就可以这样书写:CComVariant v1(100),v2(true),v3("Hello,你好"); 简单了吧?!(注4)
学生:老师,我再问最后一个问题,我如何用 VARIANT 保存一个数组?
老师:这个问题很复杂,我现在不能告诉你,我现在告诉你怕你印象不深......(注5)
学生:~!@#$%^&*()......晕!
最简单的方法就是:
1.了解组件,详细了解组件包含什么样的接口和方法;
建议使用OleView.exe程序来详细了解组件包含什么样的接口和方法。找不到,Dcomcnfg.exe也行。
引入接口
通过#import指令引入接口,例如:
#import “ABCDEFG.DLL” named_guids raw_interfaces_only no_namespace
2.初始化
调用CoInitialize()或CoInitlaizeEx()来初始化COM运行环境,例如:
 CoInitialize(0);
获取接口
根据第一步了解的知识,在初始化环境后,可以获取接口了,例如:
 IMyObject* obj = NULL; // 假定接口是IMyObject
// 返回值为HRESULT类型的,典型地,S_OK(0)表示成功,E_FAIL表示失败,还有其它的失败值
HRESULT hr = CoCreateInstance(__uuidof(MyObject), NULL, CLSCTX_ALL, __uuidof(IMyObject), (void **)&obj); 
if ( SUCCEEDED(hr) ) // 或者 if ( !FAILEd(hr) )
{
  …..利用接口作些事
  //最后释放接口
  IMyObject->Release();
}
3.方法调用
根据第一步了解的知识,调用接口的方法做某些事,例如:
HRESULT hr= obj->Method(arg1, arg2); // 方法都返回HRESULT类型的值
if ( SUCCEEDED(hr) )
{
  // 调用成功,作其它事
}
注意事项
使用COM组件,特别注意方法的参数类型,如BSTR,SAFEARRAY,VARIANT之类 ,如果有用到这些类型,请仔细参阅有关这些类型说明的资料。
4.结束
接口使用结束后,需要释放COM环境,如下:
CoUninitialize(); 
 
                    
                 
