| 首页 | 新闻 | 网页 | 设计 | 色彩 | 原创 | 视觉 | 素材 | 动漫 | 酷站 | 策划 | 文案 | 访谈 | 运营 | 编程 | 数据库 | 服务器 | 下载 | 图库 | 
您的位置: 幽幽天空 > 网页 > 编程开发 > Visual C++教程 > 文章正文 用户登录
BtoC 电子商务网站
mx.utils 包 [3] 
AS 数据类型的一些
深入BroadcasterM
ActionScript高级
ActionScript高级
探索Flash Profes
探索Flash Media 
深入解析金山毒霸
深入了解网络蠕虫

深入探索COM开发框架 之 MFC和ATL [三]           

深入探索COM开发框架 之 MFC和ATL [三]

作者:佚名 来源:CSDN 作者: RedStar81 更新:2006-8-25 21:05:35 错误报告 我要投稿

 

1.        事实上,组件类获得接口映射表是通过GetInterfaceMap()静态成员函数先

获得interfaceMap结构变量,此变量的第二个值便是接口映射表的入口.

InterfaceMap的第一个值保存了基类的_GetBaseInterfaceMap函数指针.

为在组件类中找不到接口的定义时,通过_GetBaseInterfaceMap

获得基类的interfaceMap,从而获得基类的接口映射表入口….

就这样不断上溯..

         

          通过这些宏,我们实现了接口映射表,并为在类层次中辗转提供了

          方法.这样,组件类就可以通过这张表实现接口的查询和地址定位了.

 

然而这里还有一个大问题

我们说,任何一个接口必须实现AddRef、Release、QueryInterface.

(注2:事实上,接口的定义在Idispatch出现后,有了一定的转变,你可将任何

实现了方法和数据的结合看作接口.)…可这里没见什么关于这方面的定义啊..

不错,这里还有一个”大阴谋”呢…. 关于这个还得从

#define INTERFACE_PART(theClass, iid, localClass) \

{ &iid, offsetof(theClass, m_x##localClass) }, \

//填充接口影射表

说起….

在实际的工程中,默认的上面的localClass将会被Dispatch取代.

Dispatch又为何物 ? 事实上,在CDK1.0中,COM开发不用上面这些宏,

在那里你可以清楚的看到问题的实质,没办法,时代变了,就面前的情况来

探讨吧…

上面Dispatch的位置,规定置入实现接口的嵌套类的…

那么毫无疑问Dispatch就是嵌套类啦.可是你说,这是哪里来的 ?

事实上,在CCmdTarget中,有这么一片段:

       struct XDispatch

       {

                DWORD m_vtbl;   // place-holder for IDispatch vtable

#ifndef _AFX_NO_NESTED_DERIVATION

                size_t m_nOffset;

#endif

       } m_xDispatch;

它将成为实现接口的嵌套类.

这怎么可能成为嵌套类呢 . .它什么也没有啊…简简单单的结构而已啊….

事实在内部,存在一样的虚表vtable指派行为,正是这种行为使得m_xDispatch彻底的

变了,这种行为的引爆器就是组件类构造函数中的EnableAutomation();

代码如下:

void CCmdTarget::EnableAutomation()

{

       ASSERT(GetDispatchMap() != NULL);   // must have DECLARE_DISPATCH_MAP

 

       // construct an COleDispatchImpl instance just to get to the vtable

       COleDispatchImpl dispatch;

 

       // vtable pointer should be already set to same or NULL

       ASSERT(m_xDispatch.m_vtbl == NULL||

                *(DWORD*)&dispatch == m_xDispatch.m_vtbl);

       // sizeof(COleDispatchImpl) should be just a DWORD (vtable pointer)

       ASSERT(sizeof(m_xDispatch) == sizeof(COleDispatchImpl));

 

       // copy the vtable (and other data) to make sure it is initialized

       m_xDispatch.m_vtbl = *(DWORD*)&dispatch;

       *(COleDispatchImpl*)&m_xDispatch = dispatch;

}

 

PART2 深入CCmdTarget看一看COM三大元素的实现

 

   我们之所以深入到CCmdTarget

   不是想只是为了那简简单单的实现

   我们想知道MFC对COM的一大美景:聚合

   是怎么实现的.

   二话不说,摆出架势先 :

public:

       // data used when CCmdTarget is made OLE aware

       long m_dwRef;

       LPUNKNOWN m_pOuterUnknown;  // external controlling unknown if != NULL

       DWORD m_xInnerUnknown;  // place-holder for inner controlling unknown

 

public:

       // advanced operations

       void EnableAggregation();       // call to enable aggregation

       void ExternalDisconnect();      // forcibly disconnect

       LPUNKNOWN GetControllingUnknown();

                // get controlling IUnknown for aggregate creation

 

       // these versions do not delegate to m_pOuterUnknown

       DWORD InternalQueryInterface(const void*, LPVOID* ppvObj);

       DWORD InternalAddRef();

       DWORD InternalRelease();

       // these versions delegate to m_pOuterUnknown

       DWORD ExternalQueryInterface(const void*, LPVOID* ppvObj);

       DWORD ExternalAddRef();

       DWORD ExternalRelease();

 

       // implementation helpers

       LPUNKNOWN GetInterface(const void*);

       LPUNKNOWN QueryAggregates(const void*);

 

       // advanced overrideables for implementation

       virtual BOOL OnCreateAggregates();

       virtual LPUNKNOWN GetInterfaceHook(const void*);

从上面的声明中,你可发现:

   这里声明了两套标准接口方法,

   Externalxx对应于COM模型中的委托IUnknown

  而Internalxx对应COM模型中的非委托Iunknown

 有了这两套接口方法,聚合的实现就OK了…..

 关于聚合的实现细节,欲知详情,请参阅相关专门

  的书籍,这里不再赘述.

 

通过PART1和PART2关于接口的基础构造已经完成.

 

PART3------类厂的由来

 

不用说,COM对象的创建是需要类厂的.

---------------------------------------------------------------------------------------------------------

DECLARE_OLECREATE(CSAM)宏剖析

-----------------------------------------------------------------------------

#define DECLARE_OLECREATE(class_name) \

public: \

       static AFX_DATA COleObjectFactory factory; \

   //定义类厂对象…

       static AFX_DATA const GUID guid; \

   //组件类的GUID

 

------------------------------------------------------------------------------------------------------------

                          IMPLEMENT_OLECREATE 宏剖析

                     ------------------------------------------------------------------

#define IMPLEMENT_OLECREATE(class_name, external_name, l, w1, w2, b1,\

 b2, b3, b4, b5, b6, b7, b8) \

       AFX_DATADEF COleObjectFactory class_name::factory(class_name::guid, \

                RUNTIME_CLASS(class_name), FALSE, _T(external_name)); \

//这里要注意的是external_name:ProgID

       AFX_COMDAT const AFX_DATADEF GUID class_name::guid = \

               { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }; \

//将组件类的CLSID赋予组件类的成员变量guid.

-----------------------------------------------------------------------------------------------------------

IMPLEMENT_OLECREATE(CSAM, "MFCCOM.SAM",

0x43d242f9, 0x4f7e, 0x4cbb, 0xae, 0xda, 0x77, 0x8d, 0xa1, 0x16, 0xd0, 0xd9)

说明:我们知道,在创建组件类对象时,

文章录入:skyuu    责任编辑:skyuu 
  • 上一篇文章:

  • 下一篇文章:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    发表评论:
    姓名:  评 分: 1分 2分 3分 4分 5分
     
  • 严禁发表危害国家安全、政治、黄色淫秽等内容的评论。
  • 用户需对自己在使用幽幽天空服务过程中的行为承担法律责任。
  • 本站管理员有权保留或删除评论内容。
  • 评论内容只代表机友个人观点,与本网站立场无关。