在上一节中,我看到了Queryinterface 的实现细节了, 在里面它并没有创建实例,也就是说并没有用C++的new来生成实例,它只是把this指针转换成需要的接口指针。最后一行,
用了一个AddRef()函数。该函数是IUnknown里面的方法,他是用来管理组件实例的生命周期的。因为一个组件可能在被创建出来的时候起,就被工程中多处使用,我们不知道何时来释放,所以COM标准接口中提供了对生命周期的管理的两种方法,AddRef() 和Release();
下面是用C++来实现这两个方法的:
Math(): m_nRef(0) {}
ulong Math::AddRef()
{
return InterlockedIncrement(&m_nRef);
}
ulong Math::Release()
{
if (0 ==InterlockDecrement(&m_nRef))
{
delete this;
return 0;
}
return m_nRef;
}
上面两个Interlock系列函数是为了支持多线程的。
在创建组件之前,我们先介绍一个概念: 全局特有标识符GUID, 他是独有的,128位的,具有非常高的可靠率的精确值,也叫UUID,COM使用它来识别组件类(CLSID),
接口类(IID), 类型库和组件类属(CATID)以及其它的一些东西。如
DEFINE_GUID(IID_IMATH,
0x1827709d, 0x9879, 0x4c60, 0x8b, 0x79, 0x85, 0xcd, 0x42, 0x55, 0xb9, 0xac);在vs2008上,它可以由tool --Create GUID获得。
当然你在使用IID_IMATH的时候,还得包含头文件initGuid.h
// 常用来对GUID操作的函数
IsEqualGUID(REFGUID rguid1, REFGUID rguid2); // 比较两个GUID是否相等
IsEqualIID(REFIID riid1, REFIID riid2); // 比较两个IID是否相等
IsEqualCLSID(REFCLSID , REFCLSID); // 比较两个CLSID是否相等
ProgIDFromCLSID(__in REFCLSID clsid, __deref_out LPOLESTR FAR* lplpszProgID);
COM设计者考虑到要记住CLSID并不容易,所以它通过另外一种机制来对组件命名:programmatic identifier(ProgID)它是一个简单的字符串。它通过注册表与组件相连。
只要你记得这个组件的名字,就可以通过CLSIDFromProgID函数来获得组件的CLSID.
COM以及给客户用来定位组件的信息和对组件实例化的信息被存储在注册表中,那么上面提到的内容被存放在HKEY_CLASS_ROOT的子键CLSID下面。
|
InprocServer32包含了dll文件的路径和名称
VersionIndepentProgID制定了组件当前最新的版本
LocalServer32包含了exe文件的路径和名称
CurVer 组件类最新版本的ProgID