COM原理讲述Word文档格式.docx

上传人:b****2 文档编号:1442045 上传时间:2023-04-30 格式:DOCX 页数:44 大小:151.11KB
下载 相关 举报
COM原理讲述Word文档格式.docx_第1页
第1页 / 共44页
COM原理讲述Word文档格式.docx_第2页
第2页 / 共44页
COM原理讲述Word文档格式.docx_第3页
第3页 / 共44页
COM原理讲述Word文档格式.docx_第4页
第4页 / 共44页
COM原理讲述Word文档格式.docx_第5页
第5页 / 共44页
COM原理讲述Word文档格式.docx_第6页
第6页 / 共44页
COM原理讲述Word文档格式.docx_第7页
第7页 / 共44页
COM原理讲述Word文档格式.docx_第8页
第8页 / 共44页
COM原理讲述Word文档格式.docx_第9页
第9页 / 共44页
COM原理讲述Word文档格式.docx_第10页
第10页 / 共44页
COM原理讲述Word文档格式.docx_第11页
第11页 / 共44页
COM原理讲述Word文档格式.docx_第12页
第12页 / 共44页
COM原理讲述Word文档格式.docx_第13页
第13页 / 共44页
COM原理讲述Word文档格式.docx_第14页
第14页 / 共44页
COM原理讲述Word文档格式.docx_第15页
第15页 / 共44页
COM原理讲述Word文档格式.docx_第16页
第16页 / 共44页
COM原理讲述Word文档格式.docx_第17页
第17页 / 共44页
COM原理讲述Word文档格式.docx_第18页
第18页 / 共44页
COM原理讲述Word文档格式.docx_第19页
第19页 / 共44页
COM原理讲述Word文档格式.docx_第20页
第20页 / 共44页
亲,该文档总共44页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

COM原理讲述Word文档格式.docx

《COM原理讲述Word文档格式.docx》由会员分享,可在线阅读,更多相关《COM原理讲述Word文档格式.docx(44页珍藏版)》请在冰点文库上搜索。

COM原理讲述Word文档格式.docx

每个标准的COM组件都需要一个接口定义文件,文件的扩展名为IDL。

让我们看IUnknow接口的定义文件是怎样的。

[

local,

object,

uuid(00000000-0000-0000-C000-000000000046),

pointer_default(unique)

]

interfaceIUnknown

{

typedef[unique]IUnknown*LPUNKNOWN;

cpp_quote("

//////////////////////////////////////////////////////////////////"

//IID_IUnknownandallothersystemIIDsareprovidedinUUID.LIB"

//Linkthatlibraryinwithyourproxies,clientsandservers"

HRESULTQueryInterface(

[in]REFIIDriid,

[out,iid_is(riid)]void**ppvObject);

ULONGAddRef();

ULONGRelease();

}

[local]属性禁止产生网络代码。

[object]属性是表明定义的是一个COM接口,而不是DEC风格的接口。

[uuid]属性给接口一个GUID。

[unique]属性表明null(空)指针为一个合法的参数值。

[pointer_defaul]属性所有的内嵌指针指定一个默认指针属性

typedef[unique]IUnknown*LPUNKNOWN;

这是一个类型定义

cpp_quote这个比较有趣,这是一个在idl文件写注解的方法。

这些注解将保存到***.h和***_i.c文件中

[in]表示这个参数是入参

[out]表示这个参数是出参

[iid_is(riid)]表示这个参数需要前一个的riid参数。

Iunknown:

COM要求(最基本的要求)所有的接口都需要从IUnknown接口直接或间接继承。

IUnkown接口定义了三个方法。

HRESULTQueryInterface([in]REFIIDriid,[out]void**ppv);

ULONGAddRef();

ULONGRelease();

其中AddReft()和Release()负责对象引用计数用的,而QueryInterface()方法是用于查询所实现接口用的。

每当COM组件被引用一次就应调用一次AddRef()方法。

而当客户端在释放COM组件的某个接口时就需要调用Release()方法。

这里所讲的请在下面的例子仔细体会。

COM简单的例子

此例子共有四个文件组成:

 

文件名

说明

Interface.h

接口类定义文件

Math.h和Math.cpp

实现类文件

Simple.cpp主函数文件

这里用来当作COM的客户端

interface.h文件:

#ifndefINTERFACE_H

#defineINTERFACE_H

#include<

unknwn.h>

//{7C8027EA-A4ED-467c-B17E-1B51CE74AF57}

staticconstGUIDIID_ISimpleMath=

{0x7c8027ea,0xa4ed,0x467c,{0xb1,0x7e,0x1b,0x51,0xce,0x74,0xaf,0x57}};

//{CA3B37EA-E44A-49b8-9729-6E9222CAE84F}

staticconstGUIDIID_IAdvancedMath=

{0xca3b37ea,0xe44a,0x49b8,{0x97,0x29,0x6e,0x92,0x22,0xca,0xe8,0x4f}};

interfaceISimpleMath:

publicIUnknown

public:

virtualintAdd(intnOp1,intnOp2)=0;

virtualintSubtract(intnOp1,intnOp2)=0;

virtualintMultiply(intnOp1,intnOp2)=0;

virtualintDivide(intnOp1,intnOp2)=0;

};

interfaceIAdvancedMath:

virtualintFactorial(intnOp1)=0;

virtualintFabonacci(intnOp1)=0;

#endif

此文件首先#include<

将IUnknown接口定义文件包括进来。

接下来定义了两个接口,GUID(GloballyUniqueIdentifier全局唯一标识符)它能保证时间及空间上的唯一。

ISmipleMath接口里定义了四个方法,而IAdvancedMath接口里定义了二个方法。

这些方法都是虚函数,而整个ISmipleMath与IAdvancedMath抽象类就作为二进制的接口。

math.h文件:

#include"

interface.h"

classCMath:

publicISimpleMath,publicIAdvancedMath

private:

ULONGm_cRef;

intcalcFactorial(intnOp);

intcalcFabonacci(intnOp);

//IUnknownMethod

STDMETHOD(QueryInterface)(REFIIDriid,void**ppv);

STDMETHOD_(ULONG,AddRef)();

STDMETHOD_(ULONG,Release)();

//ISimpleMathMethod

intAdd(intnOp1,intnOp2);

intSubtract(intnOp1,intnOp2);

intMultiply(intnOp1,intnOp2);

intDivide(intnOp1,intnOp2);

//IAdvancedMathMethod

intFactorial(intnOp);

intFabonacci(intnOp);

此类为实现类,他实现了ISmipleMath和IAdvancedMath两个接口类(当然也可以只实现一个接口类)。

请注意:

m_cRef是用来对象计数用的。

当m_cRef为0组件对象应该自动删除。

math.cpp文件:

math.h"

STDMETHODIMPCMath:

:

QueryInterface(REFIIDriid,void**ppv)

{//这里这是实现dynamic_cast的功能,但由于dynamic_cast与编译器相关。

if(riid==IID_ISimpleMath)

*ppv=static_cast(this);

elseif(riid==IID_IAdvancedMath)

elseif(riid==IID_IUnknown)

else{

*ppv=0;

returnE_NOINTERFACE;

}

reinterpret_cast(*ppv)->

AddRef();

//这里要这样是因为引用计数是针对组件的

returnS_OK;

STDMETHODIMP_(ULONG)CMath:

AddRef()

return++m_cRef;

Release()

ULONGres=--m_cRef;

//使用临时变量把修改后的引用计数值缓存起来

if(res==0)//因为在对象已经销毁后再引用这个对象的数据将是非法的

deletethis;

returnres;

intCMath:

Add(intnOp1,intnOp2)

returnnOp1+nOp2;

Subtract(intnOp1,intnOp2)

returnnOp1-nOp2;

Multiply(intnOp1,intnOp2)

returnnOp1*nOp2;

Divide(intnOp1,intnOp2)

returnnOp1/nOp2;

calcFactorial(intnOp)

if(nOp<

=1)

return1;

returnnOp*calcFactorial(nOp-1);

Factorial(intnOp)

returncalcFactorial(nOp);

calcFabonacci(intnOp)

returncalcFabonacci(nOp-1)+calcFabonacci(nOp-2);

Fabonacci(intnOp)

returncalcFabonacci(nOp);

CMath:

CMath()

m_cRef=0;

}

此文件是CMath类定义文件。

simple.cpp:

iostream>

usingnamespacestd;

intmain(intargc,char*argv[])

ISimpleMath*pSimpleMath=NULL;

//声明接口指针

IAdvancedMath*pAdvMath=NULL;

//创建对象实例,我们暂时这样创建对象实例,COM有创建对象实例的机制

CMath*pMath=newCMath;

//查询对象实现的接口ISimpleMath

pMath->

QueryInterface(IID_ISimpleMath,(void**)&

pSimpleMath);

if(pSimpleMath)

cout<

<

"

10+4="

<

pSimpleMath->

Add(10,4)<

endl;

//查询对象实现的接口IAdvancedMath

QueryInterface(IID_IAdvancedMath,(void**)&

pAdvMath);

if(pAdvMath)

10Fabonacciis"

pAdvMath->

Fabonacci(10)<

Release();

return0;

此文件相当于客户端的代码,首先创建一个CMath对象,再根据此对象去查询所需要的接口,如果正确得到所需接口指针,再调用接口的方法,最后再将接口的释放掉。

Math组件的二进制结构图:

小结:

例子从严格意义上来并不是真正的COM组件(他不是dll),但他已符合COM的最小要求(实现IUnknown接口)。

接下来我们来做一COMdll。

创建一个COM组件

创建过程示意图如下:

在这一过程中我们将完成三个步骤:

创建dll的入口函数,定义接口文件,实现注册功能

1.一个类型为win32dll工程:

创建一个名为MathCOM的win32dll工程。

在向导的第二步选择"

Asmipledllproject"

选项。

当然如果你选择一个空的工程,那你自己完成DllMain定义吧。

2.接口文件:

生成一个名为MathCOM.idl的接口文件。

并将此文件加入到刚才创建的那个工程里。

//MathCOM.idl文件

//MathCOM.idl:

IDLsourceforMathCOM.dll

//

//ThisfilewillbeprocessedbytheMIDLtoolto

//producethetypelibrary(MathCOM.tlb)andmarshallingcode.

import"

oaidl.idl"

;

ocidl.idl"

[

uuid(FAEAE6B7-67BE-42a4-A318-3256781E945A),

helpstring("

ISimpleMathInterface"

),

object,

pointer_default(unique)

]

interfaceISimpleMath:

IUnknown

{

HRESULTAdd([in]intnOp1,[in]intnOp2,[out,retval]int*pret);

HRESULTSubtract([in]intnOp1,[in]intnOp2,[out,retval]int*pret);

HRESULTMultiply([in]intnOp1,[in]intnOp2,[out,retval]int*pret);

HRESULTDivide([in]intnOp1,[in]intnOp2,[out,retval]int*pret);

};

uuid(01147C39-9DA0-4f7f-B525-D129745AAD1E),

IAdvancedMathInterface"

interfaceIAdvancedMath:

HRESULTFactorial([in]intnOp1,[out,retval]int*pret);

HRESULTFabonacci([in]intnOp1,[out,retval]int*pret);

uuid(CA3B37EA-E44A-49b8-9729-6E9222CAE844),

version(1.0),

helpstring("

MATHCOM1.0TypeLibrary"

libraryMATHCOMLib

importlib("

stdole32.tlb"

);

stdole2.tlb"

uuid(3BCFE27E-C88D-453C-8C94-F5F7B97E7841),

MATHCOMClass"

coclassMATHCOM

[default]interfaceISimpleMath;

interfaceIAdvancedMath;

在编译此工程之前请检查Project/Setting/MIDL中的设置。

正确设置如下图:

在正确设置后,如编译无错误,那么将在工程的目录下产生四个

作用

MathCOM.h

接口的头文件,如果想声明或定义接口时使用此文件

MathCOM_i.c

定义了接口和类对象以及库,只有在要使用到有关与GUID有关的东西时才引入此文件,此文件在整个工程中只能引入一次,否则会有重复定义的错误

MathCOM_p.c

用于存根与代理

dlldata.c

不明

3.增加注册功能:

作为COM必须要注册与注销的功能。

增加一个MathCOM.def文件,DEF文件是模块定义文件(ModuleDefinitionFile)。

它允许引出符号被化名为不同的引入符号。

//MathCOM.def文件

MathCOM.def:

Declaresthemoduleparameters.

LIBRARY"

MathCOM.DLL"

EXPORTS

DllCanUnloadNow@1PRIVATE

DllGetClassObject@2PRIVATE

DllRegisterServer@3PRIVATE

DllUnregisterServer@4PRIVATE

DllUnregisterServer 这是函数名称@4<――这是函数序号PRIVATE

接下来大致介绍一下DllRegisterServer()和DllUnregisterServer()。

(其他两个函数的作用将在后面介绍)

DllRegisterServer()和DllUnregisterServer()

DllRegisterServer()函数的作用是将COM服务器注册到本机上。

DllUnregisterServer()函数的作用是将COM服务器从本机注销。

 

MathCOM.cpp文件:

现在请将MathCOM.cpp文件修改成如下:

//MATHCOM.cpp:

DefinestheentrypointfortheDLLapplication.

stdafx.h"

objbase.h>

initguid.h>

MathCOM.h"

//standardself-registrationtable

constchar*g_RegTable[][3]={

{"

CLSID\\{3BCFE27E-C88D-453C-8C94-F5F7B97E7841}"

0,"

MathCOM"

},

CLSID\\{3BCFE27E-C88D-453C-8C94-F5F7B97E7841}\\InprocServer32"

0,

(constchar*)-1/*表示文件名的值*/},

CLSID\\{3BCFE27E-C88D-453C-8C94-F5F7B97E7841}\\ProgID"

tulip.MathCOM.1"

tulip.MathCOM.1\\CLSID"

{3BCFE27E-C88D-453C-8C94-F5F7B97E7841}"

HINSTANCEg_hinstDll;

BOOLAPIENTRYDllMain(HANDLEhModule,

DWORDul_reason_for_call,

LPVOIDlpReserved

g_hinstDll=(HINSTANCE)hModule;

returnTRUE;

/*********************************************************************

*FunctionDeclare:

DllUnregisterServer

*Explain:

self-unregistrationroutine

*Parameters:

*void--

*Return:

*STDAPI--

*Author:

tulip

*Time:

2003-10-2919:

07:

42

*****************

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 总结汇报 > 学习总结

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2