COM组件

COM组件

Risun

初稿:2004-2-19

 

 

前言

前几天我在公司的电脑被人换了,里面保存的文档、程序遭恶人陷害全部遇难,此时才发现她们的珍贵。对于以前看过的COM组件知识再次回顾,重新整理补充一下,此后要学会写学习心得更要珍惜。

 

COMComponent Object Model

 

使用组件的好处:

应用程序定制

组件库

分布式组件

 

组件要求

1.         动态链接

2.         信息封装(二进制语言无关)

 

COM是一个说明如何建立组件的规范

COM组件以Win32动态连接库(dlls)或可执行文件(EXEs)的形式发布的二进制代码

COMAPIWindows上实现的如:coCreateInstance()??

 

COM原理

接口

QueryInterface函数

接口查询:QueryInterface([in, IID] iid, [out,void **]ppv);

iid: 接口idppv:指向接口指针

 

引用计数

客户通过接口的指针来调用方法,一个组件可以被多个客户引用,何时组件注销?需要引用计数。

 

QueryInterface() 中计数增加,

 

客户显示增加引用时,需调用AddRef()增加计数

IX *pIX= pIY; pIX->AddRef();

 

客户端主动调用Release()减少计数

 

动态链接

HISTANCE LoadLibrary(

LPCTSTR lpLibFileName          //filename of DLL

);

 

FARPROC GetProcAddress(

              HMODULE        hModule,        //handle to DLL module

              LPCSTR        lpProcName      //name of function

);

进程内空间

HRESULT GUID 注册表等

HRESULT

32位,低16位代码,其余调用成功标志(1)、类型及返回值起源(15)等信息;

MAKE_HRESULT

#define MAKE_HRESULT(sev,fac,code)\ ( (HRESULT) (((unsigned long)(sev)<<31) | ((unsigned
long)(fac)<<16) \ | ((unsigned long)(code))) )

 

GUID

128位,接口或组件的ID,参数一般传递应用 REFIID

uuidgen.exe guidgen.exe

 

Windows注册表

HKEY-CLASSES_ROOT

CLSID

COM组件的相关信息记录在注册表中,注册,反注册在dll

STDAPI DllRegisterServer();

STDAPI DllUnregisterServer();

其中调用RegOpenKeyEx, RegCreateKayEx, RegSetValueEx, RegDeleteKey, RegCloseKey

 

 

COM库函数

OLE32.dllOLE32.lib

初始化

进程COM库其他函数(CoBuildVersion之外)调用CoInitialize()初始化,不需要用时CoUninitialize()(如果未调用后者会怎样??)

内存管理

1 CoGetMalloc(DWORD, LPMALLOC*)  获得接口ImallocImalloc::Alloc(), Imalloc::Free();

2 void * CoTaskMemAlloc( ULONG Cb);  void CoTaskMemFree( void *pv);

 

 

类厂

类厂是一个组件,控制组件实体的生成,一个类厂实例只能产生一种组件(看参数)

CoCreateInstance() à CoGetClassObject()  à  DllGetClassObject()          à     CreateInstance()

 COM 库函数                     COM库函数       dll中输出函数(生成类厂) 类厂方法(生成实用组件)

 

DllCanUnloadNow(), used in CoFreeUnusedLibraries() , which is called periodically to free resources by Applictaions.

 

组件复用

(暂略)

编程工作简化

(暂略)

EXE服务器

(暂略)

调度接口

IDispath;

    IDispatch : public IUnknown

    {

    public:

        virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(

            /* [out] */ UINT __RPC_FAR *pctinfo) = 0;

       

        virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(

            /* [in] */ UINT iTInfo,

            /* [in] */ LCID lcid,

            /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo) = 0;

       

        virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(

            /* [in] */ REFIID riid,

            /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,

            /* [in] */ UINT cNames,

            /* [in] */ LCID lcid,

            /* [size_is][out] */ DISPID __RPC_FAR *rgDispId) = 0;

       

        virtual /* [local] */ HRESULT STDMETHODCALLTYPE Invoke(

            /* [in] */ DISPID dispIdMember,

            /* [in] */ REFIID riid,    //reserved must be IID_NULL

            /* [in] */ LCID lcid,       //location information??

            /* [in] */ WORD wFlags,       //denote the method type

            /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,    //parameters

            /* [out] */ VARIANT __RPC_FAR *pVarResult, //returned result, if no then NULL

            /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,         //异常标志

            /* [out] */ UINT __RPC_FAR *puArgErr) = 0;              //参数错误码

};

 

typedef struct  tagDISPPARAMS    //命名参数for VB

    {

    /* [size_is] */ VARIANTARG __RPC_FAR *rgvarg;

    /* [size_is] */ DISPID __RPC_FAR *rgdispidNamedArgs;

    UINT cArgs;

    UINT cNamedArgs;

    }       DISPPARAMS;

参数被限制,只能是通过VARIANT表达的

 

调度接口

通过IDispatch::Invoke()调用实现的一系列接口

 

双重接口

IDispatch继承的COM接口,其成员函数也可以通过Invoke()方式访问

 

VARIANT

VariantInit(), VariantClear()

运行时类型检查

类型转化:VariantChangeType()

 

BSTR

SysAllocString()

SysFreeString()

 

SAFEARRAY类型

调度接口可传递的另外一种类型

???

 

类型库

语言无关适合解释性语言和宏编程语言使用的C++头文件的等价无,是IDL文件的一个编译版本,二进制

创建:midl :  idl文件中Library LibName{…} 中定义或引用的组件或接口信息

分发:独立或包含在Exe, Dll中???

使用:LoadRegTypeLib() / LoadTypeLib(), RegisterTypeLib(),  ItypeLib::GetTypeInfoOfGuid

 

通过类型库接口ITypeInfo实现IDispatch

在类型库中完成查询调度工作

 

(未完待续)

COM应用

 

COM编程思想

posted on 2004-06-19 17:34  哲学 艺术 程序 人生  阅读(804)  评论(0编辑  收藏  举报

导航