MFC对COM接口编写的支持分析

原创 2001年05月20日 16:09:00
MFC对COM的支持分析
FMD STUDIO 之 VC++编程 之 技术篇 之 :
编号
主  题
来 源
收录时间
4
MFC对COM接口编写的支持分析
自撰
00.05.08

MFC对COM的支持分析

MFC采用C++中嵌套类定义的方法实现COM接口。

为了简化其中的编写。又采用了大量的宏定义。

以下将从嵌套类实现的原始写法开始,分析MFC中对COM的支持

一、COM概述

1.COM提供了一种简洁的二进制对象使用方法。为了符合COM规范。用VC++编写的对象(类) 代码必须在编译后,能按照COM规范的格式提供"接口"。

2.关于接口,接口是一个指针,指针指向一个表格,表格内包含了能操作对象的一组函数的指针。

3.C++类定义结构对接口的支持。

为了支持多态,包含虚拟函数的C++对象都将包含一个指向虚函数表的指针,这种结构符合COM接口规范。

而操作同一对象的接口可以有多个。C++类定义中,可以用两种方案实现多个接口。

一种是多继承结构,一个类从多个接口类派生。

另一种是嵌套类定义结构。

ATL采用前者,MFC采用后者。

4.除了规范调用方法外,COM还规范了对象的建立、生存期等。

每个COM对象对应还有一个"类厂"对象,类厂对象中包含CreateInstance(..)成员,负责对象的建立,建立后,接口才有使用的可能。

而包含COM对象的组件(DLL)中,应包含一个DllGetClassObject出口函数,此函数供系统的COM库调用,在DllGetClassObject中,类厂被建立,类厂接口返回给系统COM库。

COM库根据类厂接口,调用CreateInstance建立COM对象,返回接口给用户。用户使用接口调用接口成员操作对象。

5.总结

DLL项目中要提供COM对象,需要用C++类的形式定义对象的属性和行为,但此类对用户是不可见的,用户通过接口操作类对象,因此,类的构造过程中,需要提供合适的接口,提供给用户。

为了和系统的COM库相,配合,DLL应该提供规定的几个输出函数。并提供指定对象的类厂,以及类厂中对象的建立等。

二、用C++类嵌套定义的结构提供类接口。

如果一个类定义包含一组虚函数,则其对象在内存中结构符合接口结构。

故在整个对象的封装类中,嵌套定义几个包含特定虚拟函数组合的类,以及嵌套类成员。

嵌套类的结构设置成欲提供接口的结构。(派生自I...)

例:

1.定义部分:

①接口结构的定义(虚函数组合)

class ISpellCheck : public IUnknown  //接口一 
{
 public : 
  virtual BOOL __stdcall CheckWord(String, String*) = 0;
};
class IDictionary : public IUnknown  //接口二
{
 public : 
  virtual BOOL __stdcall Initialize() = 0;
  ... ...
};

②在类定义中,嵌套定义以上接口类派生类及成员。

class CDictionary
{
 ...QueryInterface(...); file://IUnknown需要用到的调用。
 ...AddRef();
 ...Release();
 ... ...
 class XDictionaryobj:public IDictionary //接口定义
 {
  virtual ULONG _stdcall AddRef();
  ... ...
 }m_dictionaryobj; //接口成员 (其内存结构包含一个虚函数表指针,此正是接口结构所要求的。
 ... ...
 class XSpellCheckobj:public ISpellCheck
 {
  virtual ...
  ... ...
 }m_spellCheckObj;//接口成员
 ... ...
}

嵌套类中需要使用原类(CDictionary),故各嵌套类中有成员保存原类的指针。

③需要定义一个与上类配合的类厂对象类。

2.实现部分

①各成员的实现

②编写合适的IUnknown 实现

IUnknown其实是在原类中实现的。

在各嵌套类定义中,AddRef,Release,QueryInterface都调用原类中定义的公共AddRef、等函数。

QueryInterface函数中,根据传入接口ID,返回类中接口成员(m_dictionaryobj 等等)的地址。

以上结构可以构造COM接口,但书写及维护困难。

MFC采用了大量的宏来简化嵌套类的书写。由于宏的使用,在形式上看,与消息映射有些相识,但其实际编码,还是嵌套类。

③实现类厂。类厂中建立对象。

三、MFC中,接口定义

1.思路

①一个类中,包含多个接口,故包含多个嵌套类,且QueryInterface中要作多次判断。

可以抽象成为数组数据类型(映射表),添加接口简化为添加表项,查询接口简化为查表。

②嵌套类的书写复杂,用宏定义的方法简化。

③建立通用类厂

2.实现

①在类定义中添加接口映射表(DECLARE_INTERFACE_MAP),实现中添加映射表填表BEGIN_INTERFACE_MAP、END_INTERFACE_MAP等。

表项内容包括 接口标识(IID),接口成员的位置(相对对象起始地址的偏移量)

②嵌套类定义宏BEGIN_INTERFACE_PART、END_INTERFACE_PART_STATIC等。

②类定义中包含通用类厂成员COleObjectFactory factory,以及COM对象标识符成员guid,这些由宏DECLARE_OLECREATE完成

3.示例:

接口结构定义略。

定义:

class CDictionaryObj : public CCmdTarget //由CCmdTarget派生,CCmdTarget提供了接口相关支持
{
 DECLARE_DYNCREATE(CDictionaryObj) //动态创建,类厂要动态创建对象,故必需。
 ... ...
 DECLARE_OLECREATE(CDictionaryObj) //添加类厂成员,COM对象标识成员。 
 DECLARE_INTERFACE_MAP() //添加接口映射表的声明,以及相关函数的声明。
       //用此表格记录实现的接口,以及接口的位置等。
 //嵌套类的声明
 BEGIN_INTERFACE_PART(Dictionary, IDictionary)  //AddRef、Release等的声明包含在宏中。
  INIT_INTERFACE_PART(CDictionary, Dictionary)
  STDMETHOD_(BOOL, Initialize)();
  ... ...
 END_INTERFACE_PART_STATIC(Dictionary) 
 
 //第二个嵌套类
 BEGIN_INTERFACE_PART(SpellCheck, ISpellCheck)
  INIT_INTERFACE_PART(CDictionary, SpellCheck)
  STDMETHOD_(BOOL, CheckWord)(LPOLESTR, LPOLESTR *);
 END_INTERFACE_PART_STATIC(SpellCheck)
 ... ...
};

实现:

IMPLEMENT_DYNCREATE(CDictionaryObj, CCmdTarget)
//接口标识
extern "C" const IID IID_Dictionary = 
  { 0x54bf6568, 0x1007, 0x11d1,
  { 0xb0, 0xaa, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} } ;
extern "C" const IID IID_SpellCheck = 
  { 0x54bf6569, 0x1007, 0x11d1,
  { 0xb0, 0xaa, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} } ;
//接口映射表的填写
BEGIN_INTERFACE_MAP(CDictionaryObj, CCmdTarget)
 INTERFACE_PART(CDictionaryObj, IID_Dictionary, Dictionary)
 INTERFACE_PART(CDictionaryObj, IID_SpellCheck, SpellCheck)
END_INTERFACE_MAP()
//类厂实现,guid的赋值。
// {54BF6567-1007-11D1-B0AA-444553540000}
IMPLEMENT_OLECREATE(CDictionaryObj, "Dictionary.Object", 
0x54bf6567, 0x1007, 0x11d1, 0xb0, 0xaa, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00)
//各函数的实现
STDMETHODIMP_(ULONG) CDictionaryObj::XDictionary::AddRef()
{
y) //宏中定义了pThis指针,有接口映射表中记录的偏移计算出COM对象的指针,调用对象类成员。
 METHOD_PROLOGUE_EX_(CDictionaryObj, Dictionar
 return (ULONG)pThis-> ExternalAddRef(); //调用CCmdTarget基类中对IUnknown的实现。
 //在被聚合情况下,ExternalAddRef调用外部IUnknownd 的实现
 //通常情况下,调用InternalAddRef.
}

STDMETHODIMP CDictionaryObj::XDictionary::QueryInterface(
 REFIID iid, LPVOID* ppvObj)
{
 METHOD_PROLOGUE_EX_(CDictionaryObj, Dictionary) 
 //接口查询直接调用CCmdTarget的实现,其中,通过查接口映射表得知。
 return (HRESULT)pThis-> ExternalQueryInterface(&iid, ppvObj);
}
... ...


回上一页

 

阅读全文
版权声明:本文为博主原创文章,未经博主允许不得转载。

用MFC写一个COM组件

一:新建组件工程 工程名称COM     二:选择 动态链接库使用共享MFC DLL 和自动复选框   三:直接确定     四:查看自动生成代码信息 一个CCOMAp...
  • fin86889003
  • fin86889003
  • 2013年06月13日 08:47
  • 685

COM组件开发(五)——使用MFC开发COM组件

使用MFC创建一个进程内组件           这里使用的VS2008,新建一个MFC DLL项目,项目名称为“MFCCOM”,点击“确定”后进入MFC DLL向导,如下图所示:    ...
  • q5806622
  • q5806622
  • 2015年02月26日 17:21
  • 3057

7.MFC实现简单的COM

使用MFC实现简单的COM,演示了整个COM构成,注释清晰,穿插讲了MFC实现COM的原理,对照本文和代码可以弄懂整个MFC COM实现方法。...
  • wenzhou1219
  • wenzhou1219
  • 2016年07月16日 16:27
  • 1611

COM组件开发(六)——使用ATL开发COM组件

使用ATL开发COM组件           使用ATL开发COM组件之前,要对几个重要的类进行说明:           CComModule           这是ATL的中心模块类,它的...
  • q5806622
  • q5806622
  • 2015年02月27日 10:10
  • 2222

COM编程中的接口查询QueryInterface的实现原理

我们都知道,COM组件编程中,QueryInterface实现的接口之间的查询,通过这个接口,我们可以获取该组件中其他的接口。但是,QueryInterface实现的原理是什么呢,首先,我们看一下基本...
  • Andeewu
  • Andeewu
  • 2013年03月31日 17:12
  • 1527

COM组件常用接口,以备自用

COM组件有三个最基本的接口类,分别是IUnknown、IClassFactory、IDispatch。 COM组件的存在方式:DLL文件或者EXE文件; COM组件包括COM对象; COM对象包...
  • d977136629
  • d977136629
  • 2017年03月14日 16:48
  • 415

C++ COM组件的编写

COM组件的编写         本文提供一个完全用C++实现的进程内(DLL)COM服务器,不要ATL或MFC提供任何支持。用这种方式编写COM对象可以让你深入地洞察到COM处 理进程内服...
  • woshinia
  • woshinia
  • 2014年03月27日 16:40
  • 10970

VC6创建COM组件,Qt调用例子

一、建立 ATL 工程   步骤2.1:建立一个工作区(WorkSpace)。   步骤2.2:在工作区中,建立一个 ATL 工程(Project)。示例程序叫 June12,并选择DLL方式,见...
  • cibiren2011
  • cibiren2011
  • 2017年06月11日 16:00
  • 519

DLL接口的实现(COM结构思想)一

DLL接口的实现(COM结构思想)一 说到COM,我们先来看下大神对 OpenGL vs D3D 的看法: 早期的OpenGL 1.0的接口定义是C-Style的,这种API定义风格比较僵化,在扩展时...
  • u011599942
  • u011599942
  • 2013年09月06日 14:54
  • 1626

VC调用COM组件的几种方法

这篇的内容也是我在使用COM组件的时候遇到困难后在网上找的一些调用的方法,以备后用。 1.首先创建一个COM组件:myCom.ocx    组件里面有一个普通接口:ImyCom   一个方法为:Hel...
  • u013823973
  • u013823973
  • 2014年12月26日 14:42
  • 1837
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:MFC对COM接口编写的支持分析
举报原因:
原因补充:

(最多只允许输入30个字)