1.CoCreateInstance
通过传人参数CLSID创建相应组件的一个实例,并返回此组件实例的某个接口。
- CoCreateInstance的声明
HRESULT
__stdcall
CoCreateInstance(
__in REFCLSID rclsid,
__in_opt LPUNKNOWN pUnkOuter,
__in DWORD dwClsContext,
__in REFIID riid,
__deref_out LPVOID FAR* ppv
);
有四个输入参数和一个输出参数,第一个参数待创建组件的CLSID,第二个参数用于聚合组件,第三个参数是限定所创建组件的执行上下文。第三个参数组件上待使用的接口IID,最后一个参数返回接口的指针。
- CoCreateInstance的使用
//Create Component
IX *pIX = NULL;
HRESULT hr = CoCreateInstance(CLSID_Component,
NULL,
CLSCTX_INPROC_SERVER,
IID_IX,
(
void
**)&pIX);
if
(SUCCEEDED(hr))
{
pIX->Fx();
pIX->Release();
}
类上下文
CoCreatInstance第三个参数dwClsContext可以控制所创建的组件是在与客户相同的进程中允许,还是在不同的进程中运行,或者是子啊远程机器上运行。
客户可以在三种不同的上下文中使用某个组件:进程中、本地以及远程。常用组合定义:
2.类厂
CoCreateInstance实际上并没有直接创建COM组件,而是创建一个被称作类厂的组件,再由类厂创建组件,起唯一功能呢就是创建其他的组件。精确的说是某个特定的类厂将创建只同某个特定的CLSID相应的组件。客户可以通过类厂所支持的接口来对类厂创建组件的过程加以控制。创建组件的标准接口是
IClassFactory。
IClassFactory。
CoGetClassObject
CoCreate接收一个CLSID作为参数并返回指向所创建的组件中的某个接口指针。为创建同某个组件想对应的类厂,需要CoGetClassObject函数。
HRESULT
__stdcall
CoGetClassObject(
__in REFCLSID rclsid,
__in DWORD dwClsContext,
__in_opt LPVOID pvReserved,
__in REFIID riid,
__deref_out LPVOID FAR* ppv);
参数和CoCreateInstance很相似。第一个参数都是组件的CLSID.第二个参数则是创建组件的执行上下文。最后两个参数也想同,CoGetClassObject返回的是指向类厂中某个接口的指针。而CoCreateInstance是返回的指向组件中某个接口的指针。其中pServerInfo指针将被DCOM用于控制对远程组件的访问。
ICalssFactory
IClassFactory :
public
IUnknown
{
public
:
virtual
/* [local] */
HRESULT STDMETHODCALLTYPE CreateInstance(
/* [unique][in] */
IUnknown *pUnkOuter,
/* [in] */
REFIID riid,
/* [iid_is][out] */
void
**ppvObject) = 0;
virtual
/* [local] */
HRESULT STDMETHODCALLTYPE LockServer(
/* [in] */
BOOL fLock) = 0;
};
CoCreateInstance与CoGetClassObject的比较
在每次创建组件时,先创建相应的类厂,然后获取IClassFactory指针来创建所需接口比直接调用CoCreateInstance来创建所需的组件要复杂。看下如何用CoGetClassObject实现CoCreateInstance:
HRESULT
__stdcall
CoCreateInstance(
__in REFCLSID rclsid,
__in_opt LPUNKNOWN pUnkOuter,
__in DWORD dwClsContext,
__in REFIID riid,
__deref_out LPVOID FAR* ppv)
{
*ppv = NULL;
IClassFactory *pIFactory = NULL;
HRESULT hr = CoGetClassObject(rclsid,
dwClsContext,
NULL,
IID_IClassFactory,
(
void
**)&pIFactory);
if
(SUCCEEDED(hr))
{
hr = pIFactory->CreateInstance(pUnkOuter, riid,ppv);
pIFactory->Release();
}
}
可以看到CoCreateInstance首先调用CoGetClassObject来获取类厂中的ICalssFactory接口指针,再通过ICalssFactory::CreateInstance完成新组件的创建。
3.类厂的实现
DllGetClassObject的使用
CoGetClassObject需要DLL中的一个特定函数来创建组件的类厂。此函数就是DllGetClassObject。
HRESULT
__stdcall
DllGetClassObject(
__in REFCLSID rclsid,
__in REFIID riid,
__deref_out LPVOID FAR* ppv
);
这三个参数和CoGetClassObject的三个参数是相同的,将CLSID传给DllGetClassObject可以是DLL支持任意数目的组件,DllGetClassObject可以用CLSID来选择合适的类厂。
组件的创建过程
首先客户通过CoGetClassObject来启动组件的创建过程。其次是Com库他实现了CoGetClassObject函数,第三是DLL,其中实现了被CoGetClassObject叼哦那个的DllGetClassObject函数,DllGetClassObject函数的任务就是创建客户所请求的类厂。创建玩类厂后客户将使用ICalssFactory接口来创建相应的组件。
4.同一DLL中的多个组件
将待创建的组件CLSID传给DllGetClassObject来创建相应的类厂。
5.DLL的卸载
COM库实现了一个名为CoFreeUnusedLibraries函数以释放哪些不在使用的库,但何时不再使用库呢?CoFreeUnusedLibraries将调用DllCanUnloadNew以询问DLL是否可以被卸载。LockServer给客户提供了一种将服务器保存在内存中,直到使用完毕的方法,客户需要调用LockServer(True)锁住服务器。使用完毕后就可以使用LockServer(False)解锁。