参考来源:http://www.host01.com/article/software/VisualC/2006091718392288.htm
1 COM组件是一个C++类,他从一系列接口派生而来,并实现了所有的接口。这些接口都是纯虚类。
2 COM组件有三个最基本的接口类,分别是IUnknown、IClassFactory、IDispatch。
COM规范规定任何组件、任何接口都必须从IUnknown继承。
所以我们使用COM的一个简单流程如下:
//*******************************************************************************
CoInitialize(NULL);
IUnknown *pUnk=NULL;
IObject *pObject=NULL;
//第一步 通过一个Class CLSID得到COM的IUnknown指针。这是因为IUnknown是所有COM的基类,就像java中的Object类一样。由他可以转化为任意COM组件的指针。
CoCreateInstance(CLSID_Object, CLSCTX_INPROC_SERVER, NULL, IID_IUnknown, (void**)&pUnk);
//第二步 转换得到对应的COM组件指针
pUnk->QueryInterface(IID_IOjbect, (void**)&pObject);
pUnk->Release();
//第三步 通过COM组件指针调用相应接口
pObject->Func();
pObject->Release();
CoUninitialize();
//*******************************************************************************
3 IUnknown包含三个函数,分别是 QueryInterface、AddRef、Release。
QueryInterface用于查询组件实现的其它接口
AddRef用于增加引用计数,Release用于减少引用计数。
VC的各种各种的类库里已经基本上把AddRef的调用给隐含了,只需在适当的时侯调用Release。至少有两个时侯要记住调用Release,第一个是调用了QueryInterface以后,第二个是调用了任何得到一个接口的指针的函数以后。
4 IClassFactory的作用是创建COM组件,他最重要的一个函数就是CreateInstance
为什么不用new?
1)客户程序不知道组件的类名字,如果客户知道组件的类名字那组件的可重用性就要打个大大的折扣了,事实上客户程序只不过知道一个代表着组件的128位的数字串而已
2)如果组件是在远程的进程或机器上,无法new出一个对象。这时有复杂的调度过程,由类厂对象实现。
调度问题包括进程间的地址转换问题,网络间传递数据打包,解包过程
5 IDispatch叫做调度接口,主要函数是Invoke
COM组件是C++类,是靠虚函数表来调用函数的,但有许多语言没有指针(VB、VBScript、JavaScript等等),无法通过这种方式调用COM组件。
IDispatch即调度接口把每一个函数每一个属性都编上号,客户程序要调用这些函数属性的时侯就把这些编号传给IDispatch接口就行了,IDispatch再根据这些编号调用相应的函数
客户程序都调用Invoke,然后Invoke再调用相应的函数
6 IUnknown接口通过查询虚函数表调用函数,效率高,但不支持其他很多语言
自动化接口就是用IDispatch实现的接口,支持各种语言,但1)速度慢效率低(需要Invoke中转),2)只支持规定好的自动化数据类型
7 ATL中的dispinterface接口、Dual接口以及Custom接口
dual接口:双接口组件,从IDispatch继承的接口。
从IDispatch继承的接口实际上就等于有两个基类,一个是IUnknown,一个是IDispatch,所以它可以以两种方式来调用组件,可以通过IUnknown用虚函数表的方式调用接口方法,也可以通过IDispatch::Invoke自动化调度来调用,这就有了很大的灵活性
dispinterface是一种纯粹的自动化接口,这种接口就只能通过自动化的方式来调用,COM组件的事件一般都用的是这种形式的接口。
Custom接口就是从IUnknown接口派生的类,只能用虚函数表的方式来调用接口了
8 IDL,接口定义语言,COM组件的核心
支持以语言无关的方式来定义接口
9 一个典型的自注册的COM DLL所必有的四个函数
DllGetClassObject:用于获得类厂指针
DllRegisterServer:注册一些必要的信息到注册表中
DllUnregisterServer:卸载注册信息
DllCanUnloadNow:系统空闲时会调用这个函数,以确定是否可以卸载DLL
DLL还有一个函数是DllMain,这个函数在COM中并不要求一定要实现它,但是在VC生成的组件中自动都包含了它,它的作用主要是得到一个全局的实例对象。
1 COM组件是一个C++类,他从一系列接口派生而来,并实现了所有的接口。这些接口都是纯虚类。
2 COM组件有三个最基本的接口类,分别是IUnknown、IClassFactory、IDispatch。
COM规范规定任何组件、任何接口都必须从IUnknown继承。
所以我们使用COM的一个简单流程如下:
//*******************************************************************************
CoInitialize(NULL);
IUnknown *pUnk=NULL;
IObject *pObject=NULL;
//第一步 通过一个Class CLSID得到COM的IUnknown指针。这是因为IUnknown是所有COM的基类,就像java中的Object类一样。由他可以转化为任意COM组件的指针。
CoCreateInstance(CLSID_Object, CLSCTX_INPROC_SERVER, NULL, IID_IUnknown, (void**)&pUnk);
//第二步 转换得到对应的COM组件指针
pUnk->QueryInterface(IID_IOjbect, (void**)&pObject);
pUnk->Release();
//第三步 通过COM组件指针调用相应接口
pObject->Func();
pObject->Release();
CoUninitialize();
//*******************************************************************************
3 IUnknown包含三个函数,分别是 QueryInterface、AddRef、Release。
QueryInterface用于查询组件实现的其它接口
AddRef用于增加引用计数,Release用于减少引用计数。
VC的各种各种的类库里已经基本上把AddRef的调用给隐含了,只需在适当的时侯调用Release。至少有两个时侯要记住调用Release,第一个是调用了QueryInterface以后,第二个是调用了任何得到一个接口的指针的函数以后。
4 IClassFactory的作用是创建COM组件,他最重要的一个函数就是CreateInstance
为什么不用new?
1)客户程序不知道组件的类名字,如果客户知道组件的类名字那组件的可重用性就要打个大大的折扣了,事实上客户程序只不过知道一个代表着组件的128位的数字串而已
2)如果组件是在远程的进程或机器上,无法new出一个对象。这时有复杂的调度过程,由类厂对象实现。
调度问题包括进程间的地址转换问题,网络间传递数据打包,解包过程
5 IDispatch叫做调度接口,主要函数是Invoke
COM组件是C++类,是靠虚函数表来调用函数的,但有许多语言没有指针(VB、VBScript、JavaScript等等),无法通过这种方式调用COM组件。
IDispatch即调度接口把每一个函数每一个属性都编上号,客户程序要调用这些函数属性的时侯就把这些编号传给IDispatch接口就行了,IDispatch再根据这些编号调用相应的函数
客户程序都调用Invoke,然后Invoke再调用相应的函数
6 IUnknown接口通过查询虚函数表调用函数,效率高,但不支持其他很多语言
自动化接口就是用IDispatch实现的接口,支持各种语言,但1)速度慢效率低(需要Invoke中转),2)只支持规定好的自动化数据类型
7 ATL中的dispinterface接口、Dual接口以及Custom接口
dual接口:双接口组件,从IDispatch继承的接口。
从IDispatch继承的接口实际上就等于有两个基类,一个是IUnknown,一个是IDispatch,所以它可以以两种方式来调用组件,可以通过IUnknown用虚函数表的方式调用接口方法,也可以通过IDispatch::Invoke自动化调度来调用,这就有了很大的灵活性
dispinterface是一种纯粹的自动化接口,这种接口就只能通过自动化的方式来调用,COM组件的事件一般都用的是这种形式的接口。
Custom接口就是从IUnknown接口派生的类,只能用虚函数表的方式来调用接口了
8 IDL,接口定义语言,COM组件的核心
支持以语言无关的方式来定义接口
9 一个典型的自注册的COM DLL所必有的四个函数
DllGetClassObject:用于获得类厂指针
DllRegisterServer:注册一些必要的信息到注册表中
DllUnregisterServer:卸载注册信息
DllCanUnloadNow:系统空闲时会调用这个函数,以确定是否可以卸载DLL
DLL还有一个函数是DllMain,这个函数在COM中并不要求一定要实现它,但是在VC生成的组件中自动都包含了它,它的作用主要是得到一个全局的实例对象。