ATL初探(COM对象的创建过程)

ATL 创建COM对象 之前写了一篇原始dll的创建过程,以及直接使用LoadLibrary加载动态库。 但ATL所做的一个很重要的功能就是引入COM对象这个概念。 首先, ATL active template library为活动模板库,ATL为asp代码中提供COM对象应用。而一般使用活动模版库来创建COM组件。简单来说ATL一般作为方便快捷的COM开发工具使用。而ATL中使用的基本技术为 COM技术,C++模 阅读详情

在这里不说COM对象的创建过程,而只记录一下我发现谜底的过程. 本人Blog的所有原创文章,由于本人的水平非常有限,本人Blog里的所有原创文章,大多只是本人的经验,都只是为自己而写,作为记录以备后查,如有人因此而受到误导,本人全不负责.

下面的是文章正文,可能要有较好的C++基础才能看得明白,也只有受过ATL困惑和正在受到困惑的人才能看得爽,否则味同嚼蜡:

有个问题曾经困惑我,为什么我的ATL工程里,我的组件并没有实现QueryInterface等纯虚函数,却能够生成组件对象呢,答案是:ATL已经把这些可以有规律的代码帮助你自动生成了, 接口就是一组纯虚函数的集合, 生成的组件对象所属类一定都是已经实现了接口的,只是ATL帮我们做了些体力活而已.
 关于"接口是一组纯虚函数的集合"这个概念是很正确的,且不说自定义接口继承而来的AddRef等,就算我们自己添加的自定义函数,也会被ATL打下"纯虚"的烙印, 这一点可以印证:如为自定义接口IMyInterface添加方法AddLong, 可以在工程头文件MyProject.h中看到这么些代码段:
 IMyInterface:public IUnknown
    {
    public:
        virtual HRESULT STDMETHODCALLTYPE AddLong( ...) = 0;      //这里,ATL并未请示我们就把新增的函数搞成纯虚了.
    };
 这里,虽然后来我手动实现了这个纯虚函数,但仍然无法改变IMyInterface成为抽象类的命运. 但后来为什么生成了IMyInterface的对象呢? 回答只能说是被ATL装封了,我们看到的只是表面现象,不是事实.那事实是什么呢?在下面:


#ifndef A
#define A
#else
 cout<<"aaa"<<endl;       //这些与一般的if/else还是有区别的,这里,如果不执行#else,则两条输出语句都不会被执行,就好像
 cout<<"bbb"<<endl;  //在一般的if/else上加了个{}一样. 之所以写在这里,是因为在ATL的工程头文件里出现了这种用法.
#endif 

下面是工程头文件中的代码摘要:
#ifndef ....
typedef interface IInterface1 IInterface1;    //IInterface1 是接口,对应着下面的Interface1 类. 接口定义为interface
#endif           //至于为什么要来两个就不知道了,去掉一个也没报错,纯C++中来还两个报错呢.
---------------------
#ifdef __cplusplus
typedef class Interface1 Interface1;
#else          //这里,根据情况定义类为class还是struct,但要注意,上面的interface肯定是struct的
typedef struct Interface1 Interface1;      //因此接口在ATL中肯定是用struct形式实现的.
#endif
--------------------下面的一段至为关键:
#if defined(__cplusplus)&&!defined(CINTERFACE)

    IInterface1 : public IUnknown //C++风格接口,不要被它的样子蒙蔽,这个IInterface1看上去是class,其实是个struct.
    {     //不信的话可以去掉下面这个public,COM接口指针仍然能够正常调用AddLong方法而不会报错
    public:    //说调用了私有成员.
        virtual HRESULT STDMETHODCALLTYPE AddLong( long num1,long num2,long __RPC_FAR *plong) = 0;
    };                                   //STDMETHODCALLTYPE 就是STDCALL
   
#else  /* C style interface */C风格接口

    typedef struct IInterface1Vtbl //严重注意,这里不是接口,还是接口虚函数表!!!
    {
       ... QueryInterface(...);
       ... AddRef (...);
       ... Release(...);
       ... AddLong(...);          //自定义函数应该靠后.这里罗列出了所有的函数,后面就不用再说继承自IUnknown了.
    } IInterface1Vtbl;

    interface IInterface1   //这里的C风格接口的真正定义,它的内含就是一个虚函数表的指针. 上面那个#else一直管到
    {        //#endif之前.
        CONST_VTBL struct IInterface1Vtbl __RPC_FAR *lpVtbl;
    };
#define IInterface1_QueryInterface(This,riid,ppvObject)  (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
#define IInterface1_AddRef(This) /*这些#define说明了C风格接口的调用方式*/  (This)->lpVtbl -> AddRef(This)
#define IInterface1_Release(This)    (This)->lpVtbl -> Release(This)
#define IInterface1_AddLong(This,num1,num2,plong)  (This)->lpVtbl -> AddLong(This,num1,num2,plong)

#endif                                 //C风格接口定义至此才结束!!!

 至此,明白了C/C++中COM类(或称对象)与接口的不同,还有什么不明白的呢?仍然是上面说的,ATL对纯虚函数实现的封装.下面我解决最难的问题,抽象类是生成不了对象的,但抽象类可以用作指针,同样可以实现"基类指针指向派生类对象,调用的是派生类对象"的效果, ATL中,实际生成的COM对象,就是我们在ATL代码编辑器中看到的那个类(不是接口哦)的对象,ATL只是封装了QueryInterface,AddRef等方法的实现!!

 COM类与接口的关系?二者是如何组合起来的?
资料收集:
    一,在类的头文件中体现出来了,那里会有多个继承,竟然发现COM类从COM接口派生!!
    二,在工程头文件中,接口的方法都是纯虚型的,但在类的头文件中可以看出,这些类继承了接口,类中重载了这些纯虚函数,这时不再是纯虚函数,那就不是抽象类了,可以生成类的对象即COM对象了!!
    三,工程头文件中的 MyClass与类头文件中的CMyClass是一样的,都是指COM类. 不信可以去工程头文件中在MyClass的前面加个C!!
    结论:  一个类之所以容纳了多个接口,就是通过继承这多个接口,得到它们的成员! 这个生成的COM对象差点就是我们在ATL中看到的类了!!为什么说"差点"呢,因为很多书上都说"COM对象的产生过程是很复杂的",所以我很不确定,但我知道COM对象在ATL中,其实最终都是CComObject模板类的实例对象,MSDN2005的说法是: template<class Base >
class CComObject : public Base
 


 

Parameters
Base
Your class, derived from CComObjectRoot or CComObjectRootEx, as well as from any other interfaces you want to support on the object.

因此就是说,实际的COM对象是我们定义在ATL中的类的派生类的对象.


至此,我终于发现了内含,事实的真相是: ATL的类继承自它的接口,往接口中添加的函数变成纯虚函数之后,虽然接口可以实现它们,但它并未去实现这些函数,都由它们的派生类(COM类来实现),这点可去类的.CPP文件中看到! 至于客户端为什么能够准确地使用某个接口指针调用相应的函数,这就是C++的特性"基类指针(接口指针)指向派生类对象(COM对象)时,调用的是派生类的方法", C++继承时还有一个性质,基类指针指向派生类对象时,只能访问到基类中出现过的成员,最后生成对象时,再派生一次.下面的代码是俺自己写的,有点淋漓尽致的感觉:)自恋一下:

struct IMyInterface           //interface IMyInterface
{         //这段在工程头文件中看到
public:
 virtual void QueryInterface()=0;
 virtual void Add()=0;
};

//////////////////////////////////////////////////////////////////////////

struct IYourInterface         //inteface IYourInterface
{         //这段在工程头文件中看到
public:
 virtual void QueryInterface()=0;
 virtual void Dev()=0;
};

//////////////////////////////////////////////////////////////////////////
class MyClass:public IMyInterface,public IYourInterface  //class MyClass
{        //这段内容在MyClass.h头文件中看到.
 void QueryInterface();
 void Add();
 void Dev();
};
void MyClass::QueryInterface()    //这个函数是ATL封装实现的.
{
 cout<<"QueryInterface of MyClass from IUnknown"<<endl;
}
void MyClass::Add()     //这个是我们自己实现的,在MyClass.cpp中
{
 cout<<"Add of MyClass from IMyInterface"<<endl;
}
void MyClass::Dev()     //这个是我们自己实现的,在MyClass.cpp中
{
 cout<<"Dev of MyClass from IYourInterface"<<endl;
}
//////////////////////////////////////////////////////////////////////////

class CComObject:public MyClass{}; //简单继承,实现完全模拟,用它来生成最终COM对象

//////////////////////////////////////////////////////////////////////////

void main()       //这里是客户端调用COM服务
{
 IMyInterface*pMy=NULL;
 IYourInterface*pYo=NULL;
 CComObject obj;     //生成COM对象

 
 pMy=&obj;      //这里,相当于CoCreateInstance,即要COM对象也要COM接口
 pMy->Add();
 pMy->QueryInterface();

 pYo=&obj;      //这里,相当于CoCreateInstance,即要COM对象也要COM接口
 pYo->Dev();      //不过ATL中已可以通过QueryInterface实现.
 pYo->QueryInterface();
}

 一个类中可有多个接口,不过好像只能直接获得已有的其他类的已有接口,在.IDL文件中并未体现出来,但在类的头文件中体现出来了.
 一个COM组件可有多个类,这些类彼此之间是基本独立的. 我们不能通过一个对象的接口指针去获取(QueryInterface)另一个另一个对象的接口指针,这是因为QueryInterface本身没有使用COM对象作为参数(CLSID_**),QueryInterface得到接口肯定只能是本对象的另一接口,如果要得到另一对象的接口指针并调用其方法,有两种办法: 一,再调用一次CoCreateInstance或与之类似的API; 二,去ATL程序中,在COM类上右键选择"Impliment interface",再选择你想要得到其指针的接口,OK按钮一接下,在COM类就从这个接口派生了.这时重新编译ATL工程就可以了. 去客户端中就可以通过QueryInterface获取新接口的指针了.

VC++利用ATL开发COM组件 <br />  组件式软件技术已经成为当今软件技术的潮流之一。组件技术的基本思想是:将大而复杂的应用软件分成一系列的可先行实现、易于开发、理解、复用和调整的软件单元,称为组件(Components)。采用组件技术有利于在整个计算机工业中形成软件开发的规模效益,具有缩短开发时间、降低集成费用和软件维护费用等优点。同其它任何一个具有可改变部分的系统一样,标准对于组件架构也是很重要的。目前主要的标准有Microsoft的COM/DCOM,Java的JavaBeans和EJB,OMG组织的CORBA。早在几年以前, 阅读详情

相关推荐

vs2010 用ATL创建com组件

使用vs2010创建ATL项目可以自动完成复杂的com组建编写  用ATL生成com组件的步骤: 1,新建一个ATL项目,选择dll,其他默认参数即可 2,在类视图中,右击项目,添加一个类,在向导中填写类的名称,如,testClass。注意参考注意事项的第一条。此时看到多了一个ItestClass的条目。 3,右击ItestClass条目,添加一个方法,如add,设置参数,勾选in

realmagician的专栏 4626

COM组件 ATL的创建和调用

参考: - VS: VS2015创建ATL - VC:VC6.0创建ATL 实例 1. 包含两个接口: Student,Teacher 2. Student接口包含5个函数(方法) 3. Teacher接口包含3个函数(方法) 创建COM组件 ATL 1. 在接口对象文件("Student.h")添加以下代码: // Student.h : CStudent 的声明 #pragma...

fjh_tigerMan专栏 1691

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

使用ATL开发COM组件           使用ATL开发COM组件之前,要对几个重要的类进行说明:           CComModule           这是ATL的中心模块类,它的作用有点像MFC中的CWinApp,但没有后者那么庞大。它和它导出的类主要负责处理引用技术、在本地服务器内的类厂注册以及管理自动注册和自动反注册的注册表管理程序间的协调。若要创建进程内组件,只需直接使

Fish的专栏 7239

【COM/ATL 运用ATL工程创建和调用COM组件】

ATL (Active Template Library) 是一个用于简化 COM (Component Object Model) 组件开发的库。使用 ATL,你可以创建 COM 对象,这些对象可以跨进程和跨机器进行通信。下面是一个简单的步骤,说明如何使用 ATL 创建一个简单的 COM 组件,并在另一个程序中使用它。 然后在你的 ATL 类中实现这个方法: 步骤 3: 注册 COM 组件 编译你的 ATL 项目后,你需要注册你的 COM 组件。这通常可以通过运行生成的 DLL 或 EXE 文件的 /R

一起学习进步! 1703

ATL 调用COM对象

创建完COM对象后,接下来是如何调用COM组件了。这里是在c++中的调用COM对象的方法。 创建COM对象一般有三种方法,正常创建一个对象,使用CoCreateInstance函数。若在远程系统中创建一个对象,使用CoCreateInstanceEX函数。而创建多个同一CLSID的对象时,使用CoGetClassObject函数。 1.先简单的使用CoCreateInstance函数创建一个C

四夕日 月 2701

分别用MFC和ATL创建COM组件

使用MFC创建COM程序实例,使用ATL创建COM程序实例

Developing COM Components using VC-ATL

第一节 用ATL创建COM组件在 Project Name 编辑框中输入项目名如 MyProj ,并选择合适的 Location 后,按确认按钮进入下一个对话框:ATL  COM  Appwizard  -  step 1 of  1,在 Server Type 中选择 Dynamic  Link  Library [ DLL ],即进程内服务器,这是最快的组件。选中 Supp

ljx0305的专栏 2125

使用基于物质点法(MPM)的Anura3D模拟沙柱坍塌

本博客使用开源软件Anura3D软件模拟了一个沙柱坍塌的过程,这个软件是基于基于物质点法(MPM)设计的

weixin_59902634的博客 4043

用ATL创建COM组件详细解说

用ATL创建COM组件 一、创建一个模型(工程) MyProj。 二、给模型(工程)增加一个组件 MyCom。 三、给组件增加方法(函数) MyF1、MyF2、MyF3、MyF4。 一、创建模型(工程) MyProj 在VC++6.0工作平台中,点击菜单 File 下的 New 菜单项,在出现的 New 对话框中选中 P...

weixin_37972910的博客 2854

银河麒麟V10-ARM架构-postgresql安装与部署指南

本文详细介绍应用源码进行pgsql的安装步骤,本文以postgresql-12.0为例。提示:以下是本篇文章正文内容,下面案例可供参考银河麒麟系统安装程序比较繁琐,潜在问题比较多,个人建议均通过源码自定义编译安装。国产系统还需努力啊!

idols_man的博客 1万+

0009 用VisualStudio设计Max工具

这次分享个独家专利^)^:在Visual Studio中设计3dsMax脚本工具界面。 某次做原型设计时,需求改来改去,实在懒得搞GUI;虽然也尝试在Axure RP里画原型,但还是Visual Studio更顺手,也更容易测试一些交互,就直接在VS里做了。后来突发奇想,想实验一把能否直接用到Max里去,结果没想到成功了,效果还挺好。发现了新大陆,记录一下。   开始: 在VS里新建W...

whwst的专栏 769

COM组件(ATL篇)

目 录 第1章 创建进程内组件    1 1.1 目标    1 1.2 创建项目    3 1.2.1 VC++6.0    3 1.2.2 VC++2010    5 1.3 增加COM类    6 1.3.1 VC++6.0    6 1.3.2 VC++2010    8 1.3.3 项目结构  

Hanford的专栏 2692

Dify工作流构建案例:迭代驱动的多维深度搜索

为了克服这些挑战,我们可以设计一个能够智能协同内部知识库与外部互联网搜索,并最终由大型语言模型(LLM)进行深度整合与精准回答的高级工作流。

同名公众号:dify实验室 2291

ATL揭秘之“对象创建”篇

 ATL揭秘之“对象创建”篇程  化1         问题当我们用VC++ ATL工程创建了一个COM工程,实现了一个自己的COM对象,又在另一个程序中CoCreateInstance这个COM对象时,不知你是否想过这样的问题:COM对象是用C++类对象实现的,但是,我们从来没有在自己的代码中创建这些C++类对象——比如,“new”这些对象。那么,实现COM对象的C++对象是由谁

5507

汇川Easy系列PLC系统PID指令编程应用(增量型)

增量式PIDS7-1200/1500增量式PID(输出归一化、支持PWM输出)_西门子1200pid算法公式-优快云博客文章浏览阅读1k次。本文介绍了S7-1200/1500 PLC中增量式PID算法的应用,包括输出归一化和PWM输出。通过详细解析,阐述了PID输出如何限制在0.0-1.0之间,并且如何将PID输出与PWM占空比关联,适用于温度等控制场景。

RXXW_Dor的博客 1422

openCv +3.4.0 车牌定位(C++版本)

#include <iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc.hpp> #include "opencv2/shape.hpp" using namespace ...

Bamboo265925的博客 2337

[COM/ATL]组件、对象、MFC、ATL的区别

组件(Component)和对象(Object)之间的区别 先明确组件(Component)和对象(Object)之间的区别。组件是一个可重用的模块,它是由一 组处理过程、数据封装和用户接口组成的业务对象(Rules Object)。组件看起来像对象,但不符合对象的学术定义。它们的主要区别是:  组件可以在另一个称为容器(有时也称为承载者或宿主)的应用程序中使用,也可以作为独立过程使用

超越 2853

黑猫带你学UFS协议第23篇:UFS固件升级操作详解(FFU)

摘要:本文介绍了UFS固件更新(FFU)的实现方法与注意事项。根据UFS3.1 JEDEC协议,FFU通过write buffer命令(MODE=0Eh)下载FW固件,随后必须进行power cycle或硬件复位生效。文章详细阐述了FFU操作的10条规则,包括数据分片传输要求、寄存器访问限制等,同时指出协议未明确的厂商实现差异。关键寄存器包括bFFUTimeout、bDeviceFFUStatus和fPermanentlyDisableFwUpdate。

黑猫奥利奥的博客 1万+

COM编程攻略(四 COM对象创建的原理及ATL实现)

COM编程攻略(四 COM对象创建的原理及ATL实现)

heusunduo88的博客 1465

2022年全国职业院校技能大赛网络系统管理赛项模块A:网络构建(样题5)-网络部分解析-附详细代码

2022年全国职业院校技能大赛网络系统管理赛项模块A:网络构建(样题5)-网络部分解析-附详细代码

bfq05234214的博客 416

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

进程内COM对象的创建过程(AC5)

  AC5,由VS2005的ATL向导生成的默认COM对象代码分析ATL如何实现COM,第五部分。  Com库创建COM对象可以使用三个方法:CoCreateInstance(IN REFCLSID rclsid, IN LPUNKNOWN pUnkOuter, IN DWORD dwClsContext, IN REFIID riid, OUT LPVOID FAR* ppv);

win2ks 3444

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

ATL入门:利用ATL编写简单的COM组件

序论       第一步:运行ATL COM Wizard         运行Visual C++ 并创建一个新的工程,选择“ATL COM AppWizard”,项目名称为”Simple_ATL”。设置好项目的保存路径,单击“OK”,你将看到弹出的一个对话框,如下所示:           我们将创建一个Server DLL, 故在“Server Type”项中选择“D

王兆华的专栏 7975

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

ATL COM appWizard

2010-12-03 15:09ATL,Active Template Library活动模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。通过活动模板库,可以建立COM组件,然后通过ASP页面中的脚本对COM对象进行调用。这种COM组件可以包含属性页、对话框等等控件。 <br />ATL简介 <br />一. 什么是ATL <br />自从1993年Microsoft首次公布了COM技术以后,Windows平台上的开发模式发生了巨大的变化,以COM为基础的一系列软件组件

计算机科学与技术 6951

用ATL建立轻量级的COM对象

本文假设你熟悉C++和COM。摘要:    ATL——活动模板库(The Active Template Library),其设计旨在让人们用C++方便灵活地开发COM对象。ATL本身相当小巧灵活,这是它最大的优点。用它可以创建轻量级的,自包含的,可复用的二进制代码,不用任何附加的运行时DLLs支持。    由于COM技术良好的口碑,越来越多的程序员已经走进或正在走进COM的编程世界。它就像盛夏里

Alvin-He的专栏 1775

初学者教程:ATL/COM简单工程

原作者:C. Lung原文链接:http://www.codeproject.com/atl/com_atl.asp点这里下载本文配套源代码介绍  本教程的目的是告诉你如何使用ATL创建一个COM服务器,并使用Visual C++和Visual Basic程序来分别调用这个服务器。我并不想深入探讨COM的细节,也不想让你深陷于IDL之中。这一教程只是为VC++的新手程序员设计的,告诉他们利用ATL

马说@优快云 6482
下一篇: 一个完整托盘程序的实现
biblereader
博客等级 码龄20年 11粉丝 18原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值