一、关于ProgID和GUID的API 函数 | 功能说明 | CLSIDFromProgID()、CLSIDFromProgIDEx() | 由 ProgID 得到 CLSID。没什么好说的,你自己都可以写,查注册表贝 | ProgIDFromCLSID() | 由 CLSID 得到 ProgID,调用者使用完成后要释放 ProgID 的内存(注5) | CoCreateGuid() | 随机生成一个 GUID | IsEqualGUID()、IsEqualCLSID()、IsEqualIID() | 比较2个ID是否相等 | StringFromCLSID()、StringFromGUID2()、StringFromIID() | 由 CLSID,IID 得到注册表中CLSID样式的字符串,注意释放内存 |
二、关于数据类型(字符串)
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。 |
ATL转换
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 |
上表中的宏函数,其实非常容易记忆:
2 | 好搞笑的缩写,to 的发音和 2 一样,所以借用来表示“转换为、转换到”的含义。 | A | ANSI 字符串,也就是 MBCS。 | W、OLE | 宽字符串,也就是 UNICODE。 | T | 中间类型T。如果定义了 _UNICODE,则T表示W;如果定义了 _MBCS,则T表示A | C | const 的缩写 |
三、关于内存空间
| C语言 | C++语言 | Windows 平台 | COM | IMalloc 接口 | BSTR | 申请 | malloc() | new | GlobalAlloc() | CoTaskMemAlloc() | Alloc() | SysAllocString() | 重新申请 | realloc() | | GlobalReAlloc() | CoTaskRealloc() | Realloc() | SysReAllocString() | 释放 | free() | delete | GlobalFree() | CoTaskMemFree() | Free() | SysFreeString() |
以上这些函数必须要按类型配合使用(比如:new 申请的内存,则必须用 delete 释放)。在 COM 内部,当然你可以随便使用任何类型的内存分配释放函数,但组件如果需要与客户进行内存的交互,则必须使用上表中的后三类函数族。
1、BSTR 内存在上回中,已经有比较丰富的介绍了,不再重复;
2、CoTaskXXX()函数族,其本质上就是调用C语言的函数(malloc...);
3、IMalloc 接口又是对 CoTaskXXX() 函数族的一个包装。包装后,同时增强了一些功能,比如:IMalloc::GetSize()可以取得尺寸,使用 IMallocSpy 可以监视内存的使用;
四、参数传递方向
在C语言的函数声明中,尤其当参数为指针的时候,你是看不出它传递方向的。比如:
void fun(char * p1, int * p2);
请问,p1、p2 哪个是入参?哪个是出参?甚或都是入参或都是出参?由于牵扯到内存分配和释放等问题,COM 需要明确标注参数方向。
以后我们写程序,就类似下面的样子:
HRESULT Add([in] long n1, [in] long n2, [out] long *pnSum); // IDL文件(注2)
STDMETHOD(Add)(/*[in]*/ long n1, /*[in]*/ long n2, /*[out]*/ long *pnSum); // .h文件
如果参数是动态分配的内存指针,那么遵守如下的规定:
方向 | 申请人 | 释放人 | 提示 | [in] | 调用者 | 调用者 | 组件接收指针后,不能重新分配内存 | [out] | 组件 | 调用者 | 组件返回指针后,调用者“爱咋咋地”(注3) | [in,out] | 调用者 | 调用者 | 组件可以重新分配内存 |
|