COM学习笔记Word文件下载.docx
- 文档编号:5096386
- 上传时间:2023-05-04
- 格式:DOCX
- 页数:39
- 大小:131.06KB
COM学习笔记Word文件下载.docx
《COM学习笔记Word文件下载.docx》由会员分享,可在线阅读,更多相关《COM学习笔记Word文件下载.docx(39页珍藏版)》请在冰点文库上搜索。
}
Release(void)
m_RefCount--;
if(m_RefCount==0)
deletethis;
return0;
}
由于每一个对象都支持IUnknown接口,因此可以通过QueryInterface()来询问对象是否支持您感兴趣的其它接口。
接口通过接口ID来标识。
HRESULTIUnknown:
QueryInterface(REFIIDriid,LPVOIDFAR*ppv)
if(riid==IID_IUnknown||riid==IID_IDropTarget)
*ppv=(LPVOID)this;
AddRef();
ReturnS_OK;
else{
*ppv=NULL;
returnE_NOINTERFACE;
用于唯一地区分COM中条目的标识符是一个被称为GUID(全局唯一标识符)或UUID(通用唯一标识符)。
Typedefstruct_GUID
unsignedlongData1;
unsignedshortData2;
unsignedshortData3;
unsignedcharData[8];
}GUID;
GUID的取值范围非常大,16个字节可能形成的不同组合为3.4ⅹ10^38。
在COM中传输格式化数据的工作是通过数据对象处理的,数据对象是支持IDataObject接口的对象。
IDataObject接口支持以下方法:
IDataObject:
GetData
GetDataHere
QueryGetData
GetCanonicalFormatEtc
SetData
EnumFormatEtc
DAdvise
DUnadvise
EnumDAdvise
决定了设计方案以及接口中需要包括的方法和参数后,必须使用接口描述语言(IDL)编写接口的抽象定义。
编写好.IDL文件后,使用VC++和PlatformSDK自带得MicrosoftIDL编译器编译,并生成头文件、勇于构建调度借口调用的代理和占为程序的代码以及实现开发工具和调用接口所必需的类型库。
自动化,通过它COM对象可以将其功能提供给解释型客户(如脚本编写语言)而不是编译型客户使用。
在开发阶段,当COM接口客户被编译时,编译器读取源代码,通过查阅头文件或类型库中的接口定义将方法名称解析为VTBL条目,并生成目标代码,以便将必须的参数压入堆栈并跳到接口VTBL中相应条目保存的地址。
编译过程可能需要很长时间,但编译后运行二进制代码的速度相对较快。
而解释型客户在真正执行之前,不会将源代码解析为机器代码。
自动化对象通过一个叫做IDispatch的标准接口暴露其所有的功能,而不是将每项功能作为自定义接口的VTBL中的条目来暴露。
对对象的任何内部方法的调用都是通过该接口进行处理的。
IDispatch接口的方法包括:
IDispatch:
Invoke
GetIDsOfNames
GetTypeInfo
GetTypeInfoCount
当客户想调用自动化对象的内部方法时,它调用对象的IDispatch:
Invoke()。
客户可使用IDispatch:
GetIDsOfNames获得想要做事情的ID。
类型库是对象厂商提供的静态数据结构的集合,通过ItypeLib接口进行访问,包含关于单个对象、接口或类的信息。
类型库可以包含描述下述内容的信息:
服务器支持的对象类型
·
每个对象方法及其参数和类型
每个对象属性及其类型
枚举常量值
到在线文档中特定条目的引用
COMLanguageRequirements
TheonlylanguagerequirementforCOMisthatcodeisgeneratedinalanguagethatcancreatestructuresofpointersand,eitherexplicitlyorimplicitly,callfunctionsthroughpointers.Object-orientedlanguagessuchasC++andSmalltalk?
provideprogrammingmechanismsthatsimplifytheimplementationofCOMobjects,butlanguagessuchasC,Pascal,Ada,
Java,andevenBASICprogrammingenvironmentscancreateanduseCOMobjects.
以上摘自MSDN,重要的是C,Pascal,Ada,Java,andevenBASIC都可以用来编写COM。
以上初步介绍了关于COM的一些东西,不多也很浅,理解以上的部分就够花费很长一段时间的了,如果真地对COM感兴趣的话,最好有一定的基础,包括:
数据结构,面向对象的程序设计,Windows编程等,不过也不一定都学,只是这些会对你学习COM并在短时间内掌握并深入理解COM会有相当的好处。
COM学习笔记
(二)CoCreateInstance具体内部实现
[cpp]
viewplaincopy
1.
CoCreateInstance(....)
2. {
3. //.......
4. IClassFactory
*pClassFactory=NULL;
5. CoGetClassObject(CLSID_Object,
CLSCTX_INPROC_SERVER,
NULL,
IID_IClassFactory,
(void
**)&
pClassFactory);
6. pClassFactory->
CreateInstance(NULL,
IID_IUnknown,
(void**)&
pUnk);
7. pClassFactory->
Release();
8. //........
9.}
这段话的意思就是先得到类厂对象,再通过类厂创建组件从而得到IUnknown指针。
继续深入一步,看看CoGetClassObject的内部伪码:
CoGetClassObject(.....)
2.{
3. //通过查注册表CLSID_Object,得知组件DLL的位置、文件名
4. //装入DLL库
5. //使用函数GetProcAddress(...)得到DLL库中函数DllGetClassObject的函数指针。
6. //调用DllGetClassObject
7.}
8./// DllGetClassObject是干什么的,它是用来获得类厂对象的。
只有先得到类厂才能去创建组件.
9./// 下面是DllGetClassObject的伪码:
10. DllGetClassObject(...)
11. {
12. //......
13. CFactory*
pFactory=
new
CFactory;
//类厂对象
14. pFactory->
QueryInterface(IID_IClassFactory,
15. //查询IClassFactory指针
16. pFactory->
17. //......
18. }
19./// CoGetClassObject的流程已经到此为止,现在返回CoCreateInstance,看看CreateInstance的伪码:
20. CFactory:
CreateInstance(.....)
21. {
22. //...........
23. CObject
*pObject
=
CObject;
//组件对象
24. pObject->
QueryInterface(IID_IUnknown,
25. pObject->
26. //...........
27. }
这部分我们将构造一个创建COM组件的最小框架结构,然后看一看其内部处理流程是怎样的
1.IUnknown
*pUnk=NULL;
2.IObject
*pObject=NULL;
3.CoInitialize(NULL);
4.CoCreateInstance(CLSID_Object,
5.pUnk->
QueryInterface(IID_IOjbect,
pObject);
6.pUnk->
7.pObject->
Func();
8.pObject->
9.CoUninitialize();
1.CoCreateInstance(....)
3. .......
4. IClassFactory
5. CoGetClassObject(CLSID_Object,
6. pClassFactory->
7. pClassFactory->
8. ........
9. }
这就是一个典型的创建COM组件的框架,不过我的兴趣在CoCreateInstance身上,让我们来看看它内部做了一些什么事情。
以下是它内部实现的一个伪代码:
1.CoGetClassObject(.....)
3. //通过查注册表CLSID_Object,得知组件DLL的位置、文件名
4. //装入DLL库
5. //使用函数GetProcAddress(...)得到DLL库中函数DllGetClassObject的函数指针。
6. //调用DllGetClassObject
7. }
8. DllGetClassObject是干什么的,它是用来获得类厂对象的。
9. 下面是DllGetClassObject的伪码:
10. DllGetClassObject(...)
11. {
12. ......
13. CFactory*
14. pFactory->
15. //查询IClassFactory指针
16. pFactory->
17. ......
18. }
19. CoGetClassObject的流程已经到此为止,现在返回CoCreateInstance,看看CreateInstance的伪码:
20. CFactory:
21. {
22. ...........
23. CObject
24. pObject->
25. pObject->
26. ...........
27. }
上图是从COM+技术内幕中COPY来的一个例图,从图中可以清楚的看到CoCreateInstance的整个流程。
(7)一个典型的自注册的COMDLL所必有的四个函数
DllGetClassObject:
用于获得类厂指针
DllRegisterServer:
注册一些必要的信息到注册表中
DllUnregisterServer:
卸载注册信息
DllCanUnloadNow:
系统空闲时会调用这个函数,以确定是否可以卸载DLL
DLL还有一个函数是DllMain,这个函数在COM中并不要求一定要实现它,但是在VC生成的组件中自动都包含了它,它的作用主要是得到一个全局的实例对象。
(8)注册表在COM中的重要作用
首先要知道GUID的概念,COM中所有的类、接口、类型库都用GUID来唯一标识,GUID是一个128位的字串,根据特制算法生成的GUID可以保证是全世界唯一的。
COM组件的创建,查询接口都是通过注册表进行的。
有了注册表,应用程序就不需要知道组件的DLL文件名、位置,只需要根据CLSID查就可以了。
当版本升级的时侯,只要改一下注册表信息就可以神不知鬼不觉的转到新版本的DLL。
COM学习笔记(三)IUnknown接口
一:
接口定义
任何一个接口都是继承于IUnknown接口。
客户同组件的交互都是通过一个接口完成的。
在客户查询组件的其他接口时,也是通过接口完成的。
这个接口就是Iunkown,它的定义包含在Win32SDK中的UNKOWN.h头文件中。
1.interface
IUnkown
2.
3.{
4.
5.
virtual
HRESULT
__stdcall
QueryInterface(const
IID&
iid,
void**
ppv)
0;
6.
7.
ULONG
AddRef()
8.
9.
Release()
10.
11.};
2.
获取IUnkown指针
有一个叫CreateInstance的函数,它可以建立一个组件并返回一个IUkown指针:
IUnkown*CreateInstance();
在此,客户不必再使用new操作符。
3.
QueryInterface函数
客户可使用IUnkown中的成员函数QueryInterface查询组件是否支持某个特定的接口,如果支持,将返回一个指向此接口的指针;
如果不支持,则返回一个错误代码。
HRESULT__stdcallQueryInterface(constIID&
iid,void**ppv);
其中,第一个参数iid标志客户所需的接口,第二个参数ppv存放所请求接口的指针地址。
4.
使用QueryInterface
1.IUnkown*
pI;
2.//define
a
pointer
for
the
interface
3.IX*
pIX
NULL;
4.//ask
IX
5.HRESULT
hr
pI->
QueryInterface(IID.IX,
(void**)
&
pIX);
6.//check
return
value
7.if(SUCCEEDED(hr))
8.{
//use
pIX->
fx();
11.}
在这段代码中,我们查询了pI是否支持由IID.IX所标识的接口。
若成功返回,那么我们就可以使用它返回的指针了。
5.
QueryInterface的实现
QueryInterface需要根据某个给定的IID返回指向相应接口的指针。
如果组件支持客户指定的接口,那么返回S_OK及相应的指针,否则,返回E_NOINTERFACE并将相应的指针返回值设为NULL。
例如我们有类CA,及其接口的继承关系:
1.HRESULT
CA:
3.
if(iid
==
IID.IUnkown)
{
//the
client
wants
*ppv
static_cast<
IX*>
(this);
}
else
IDD.IX)
11.
12.
13.
14.
if
(iid
IDD.IY)
15.
16.
IY
17.
IY*>
18.
19.
20.
21.
//we
don'
t
support
wants.
22.
//be
sure
to
set
resulting
NULL
23.
24.
E_NOINTERFACE;
25.
26.
IUnkown*>
(*ppv)->
AddRef();
27.
S_OK;
28.}
在这里,QueryInterface使用一个简单的if-then-else语句实现。
当然用其他任何一种可以将一种类型映射成另外一种类型的结构也是可以实现的。
如可用数组、哈希表或树来实现。
6.
QueryInterface的实现规则
(1)
QueryInterface必须总是返回同一IUnkown指针
可以通过查询两个接口的IUnkown接口,并比较其返回值来确定这两个接口是否指向同一组件。
(2)
若客户曾经获取过某个接口,那么它将总能
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- COM 学习 笔记