COM组件(ATL篇)
目录
第1章创建进程内组件
1.1 目标
本章的目标是使用ATL创建一个进程内COM组件。在此组件里,将实现COM类CStatistic及COM接口IStatistic,用来进行统计计算。IStatistic的详细信息如下:
1、方法
void Reset(); //重新开始统计计算
void Add(double dVal); //增加一个数据
2、属性
long Count; //返回数据个数
double Average; //返回平均值
double StdDev; //返回标准差
CStatistic的VC++代码如下:
#include <MATH.H> class CStatistic { public: CStatistic() {Reset();} public: void Reset() {memset(this,0,sizeof(*this));} void Add(double dVal) { ++m_nCount; //样本个数 m_dSum += dVal; //所有样本值的和 m_dSum2 += dVal * dVal; //所有样本值的平方和 } public://属性定义(VC++的语法) __declspec(property(get=GetCount)) ULONG Count; __declspec(property(get=GetAverage)) double Average; __declspec(property(get=GetStdDev)) double StdDev; public: ULONG GetCount() const {return m_nCount;} double GetAverage() const { if(m_nCount) { return m_dSum / m_nCount; } return 0.0; } double GetStdDev() const { double d = 0.0; if(m_nCount > 1) { d = (m_nCount * m_dSum2 - m_dSum * m_dSum) / (m_nCount * (m_nCount - 1)); if(d > 0.0) { d = sqrt(d); } } return d; } private: ULONG m_nCount; //样本个数 double m_dSum; //所有样本值的和 double m_dSum2; //所有样本值的平方和 }; |
测试代码如下:
ULONG n = 0; double d = 0.0; CStatistic s; s.Reset(); s.Add(1.0); s.Add(2.0); s.Add(3.0); s.Add(4.0); n = s.Count; //(1,2,3,4)的个数 d = s.Average; //(1,2,3,4)的平均值 d = s.StdDev; //(1,2,3,4)的标准差 s.Add(5.0); n = s.Count; //(1,2,3,4,5)的个数 d = s.Average; //(1,2,3,4,5)的平均值 d = s.StdDev; //(1,2,3,4,5)的标准差 |
这个类的优点在于:它能实时获得样本数据的平均值、标准差,且不用把样本数据存入数组,因此可以连续的长时间工作。
1.2 创建项目
1.2.1 VC++6.0
运行VC++6.0,新建"ATL COM AppWizard"项目,如下图所示。配置好项目名称、项目目录后,单击"OK"按钮。
图1.1
显示界面如下所示,直接单击"Finish"按钮。
图1.2
显示界面如下,单击"OK"按钮,完成项目创建。
图1.3
1.2.2 VC++2010
运行VC++2010,新建"ATL Project"项目,如下图所示。配置好项目名称、项目目录后,单击"OK"按钮。
图1.4
显示创建向导,界面如下面两张图所示:
图1.5 创建向导——页面一
图1.6 创建向导——页面二
单击上图的"Finish"按钮,完成项目的创建。
1.3 增加COM类
现在,往项目里增加COM类。
1.3.1 VC++6.0
单击【Insert】【New ATL Object...】菜单项
图1.7
显示界面如下。请选中"Objects"里的"Simple Object",然后单击"Next"按钮。
图1.8
显示界面如下,一共有两个页面。
图1.9 增加COM类——页面一
下图所示界面里,Interface有两个选项:Dual表示双接口(也叫自动化接口),它派生自IDispatch;Custom表示自定义接口,它派生自IUnknown。自定义接口直接访问虚函数表,其效率较高。自动化接口效率较低,但是它支持的语言较多。
图1.10 增加COM类——页面二
1.3.2 VC++2010
单击【Project】【Add Class...】菜单项
图1.11
选中"ATL Simple Object",然后单击"Add"按钮
图1.12
显示界面如下,一共有三个页面
图1.13 增加COM类——页面一
图1.14 增加COM类——页面二
图1.15 增加COM类——页面三
1.3.3 项目结构
VC++6.0的类视图里增加了"CStatistic"和"IStatistic"。
IStatistic是COM接口,客户端程序通过它访问COM组件。
CStatistic是COM类,真正的工作由它来完成。
图1.16
同时,idl文件也发生了变化,如下表所示。增加了接口IStatistic,增加了COM类Statistic,这个COM类实现了接口IStatistic。
// comDLLatl.idl import "oaidl.idl"; import "ocidl.idl"; [ uuid(0FEBC618-38BC-4A5B-AE09-3C56635F4D73), version(1.0), helpstring("comDLLatl 1.0 Type Library") ] library COMDLLATLLib { importlib("stdole32.tlb"); importlib("stdole2.tlb"); [ object, uuid(7FB59FA6-E715-4C23-9520-DE93293E0B5F), helpstring("IStatistic Interface"), pointer_default(unique) ] interface IStatistic : IUnknown { }; [ uuid(471BF24D-B793-44A1-9205-7BF36A6EB698), helpstring("Statistic Class") ] coclass Statistic { [default] interface IStatistic; }; }; |
1.4 增加方法
1.4.1 VC++6.0
鼠标右键单击接口IStatistic,弹出菜单中单击【Add Method...】菜单项
图1.17
下图就是增加方法的界面。这里增加了方法void Add(double dVal)。单击"OK"按钮,完成方法的增加。注意:对于自动化接口,Return Type只能是HRESULT。
图1.18
可使用同样的方法,增加方法void Reset()。
1.4.2 VC++2010
鼠标右键单击接口IStatistic,弹出菜单中单击【Add】【Add Method...】。
图1.19
增加方法的界面如下。与VC++6.0的大致相同。单击"Finish"按钮,完成方法void Add(DOUBLE dVal)的添加。
图1.20
可使用同样的方法,增加方法void Reset()。
1.5 增加属性
1.5.1 VC++6.0
在图1.17中,单击【Add Property...】菜单项。显示界面如下:
这里增加了属性long Count。注意:没有设置"Put function",说明这个属性是只读属性。
单击"OK"按钮,完成属性的增加。
图1.21
同样方法,可以增加属性double Average和double StdDev。
1.5.2 VC++2010
在图1.19中,单击【Add Property...】菜单项。显示界面如下:
这里增加了属性ULONG Count。注意:没有设置"Put function",说明这个属性是只读属性。
单击"Finish"按钮,完成属性的增加。
图1.22
同样方法,可以增加属性double Average和double StdDev。
1.6 删除方法、属性
使用ATL,删除属性、方法,似乎只能手动进行,相当的麻烦。
1.7 编码
1.7.1 增加成员变量
请给CStatistic增加三个成员变量
private: ULONG m_nCount; double m_dSum; double m_dSum2; |
1.7.2 初始化成员变量
CStatistic的构造函数里,初始化这三个成员变量
CStatistic() { m_nCount = 0; m_dSum = 0.0; m_dSum2 = 0.0; } |
1.7.3 实现Add
STDMETHODIMP CStatistic::Add(double dVal) { ++m_nCount; //样本个数 m_dSum += dVal; //所有样本值的和 m_dSum2 += dVal * dVal; //所有样本值的平方和 return S_OK; } |
1.7.4 实现Reset
STDMETHODIMP CStatistic::Reset() { m_nCount = 0; m_dSum = 0.0; m_dSum2 = 0.0; return S_OK; } |
1.7.5 实现get_Count
STDMETHODIMP CStatistic::get_Count(long *pVal) { *pVal = m_nCount; return S_OK; } |
1.7.6 实现get_Average
STDMETHODIMP CStatistic::get_Average(double *pVal) { if(m_nCount) { *pVal = m_dSum / m_nCount; } else { *pVal = 0.0; } return S_OK; } |
1.7.7 实现get_StdDev
STDMETHODIMP CStatistic::get_StdDev(double *pVal) { *pVal = 0.0; if(m_nCount > 1) { *pVal = (m_nCount * m_dSum2 - m_dSum * m_dSum) / (m_nCount * (m_nCount - 1)); if(*pVal > 0.0) { *pVal = sqrt(*pVal); } } return S_OK; } |
1.8 注册、注销
编译comDLLatl,即可得到进程内COM组件comDLLatl.dll。使用它之前,需要注册。
注册组件可使用如下任意一条命令。它们原理相同:都是载入comDLLatl.dll,然后调用DllRegisterServer函数
regsvr32 comDLLatl.dll |
Rundll32 comDLLatl.dll,DllRegisterServer |
注销组件可使用如下任意一条命令。它们原理相同:都是载入comDLLatl.dll,然后调用DllUnregisterServer函数
regsvr32 /u comDLLatl.dll |
Rundll32 comDLLatl.dll,DllUnregisterServer |
注意:VC++2010可以编译生成64位的COM组件。在64位操作系统上,regsvr32.exe和Rundll32.exe将自动识别COM组件是32位的还是64位的。注册信息会写入注册表的如下几个位置。注意这里的<ProgID>其实就是comDLLatl.Statistic。
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\TypeLib\ HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface\ HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID HKEY_LOCAL_MACHINE\SOFTWARE\Classes\<ProgID> |
对于64位组件,注册程序直接访问上述注册表项;对于32位组件,注册程序会将上述注册表项映射至32位的注册表项。如此一来,同一个组件的32位、64位是可以同时注册在64位Windows上的,它们互不干涉。
第2章 VC++使用组件
2.1 #import
请参考《COM组件(MFC篇)》。需要注意的是:MFC创建的COM组件,其接口必定是Dual接口(图1.10、图1.15中的Interface选项),也就是派生自IDispatch的自动化接口。ATL可以创建Custom接口,这种接口将派生自IUnknown,tli文件里的函数通过虚函数实现,效率较高。Custom接口的不足之处在于:它可能不能被某些脚本语言(如:VBS)调用。
2.2 MFC包装类
如果接口是Dual接口,就可以生成MFC包装类。具体操作请参考《COM组件(MFC篇)》。
2.3 C语言调用
使用C语言也可以访问COM组件。
如果接口是Dual接口,请参考《COM组件(MFC篇)》。
如果接口是Custom接口,则可以使用编译类型库时产生的C/C++头文件。如下面这段代码:(节选自comDLLatl_i.h)
#define IStatistic_Add(This,dVal) ((This)->lpVtbl->Add(This,dVal)) #define IStatistic_get_Count(This,pVal) ((This)->lpVtbl->get_Count(This,pVal)) |
亦即:可以通过宏IStatistic_Add、IStatistic_get_Count去访问方法、属性。
COM组件(ATL篇)的更多相关文章
- JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐(二)
前言:上篇 JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐 分享了几个项目中比较常用的组件,引起了许多园友的关注.这篇还是继续,因为博主觉得还有几个非常简单.实用的组件,实在不愿自己 ...
- 【转】JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐(二)
前言:上篇 JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐 分享了几个项目中比较常用的组件,引起了许多园友的关注.这篇还是继续,因为博主觉得还有几个非常简单.实用的组件,实在不愿自己 ...
- 数百个 HTML5 例子学习 HT 图形组件 – 拓扑图篇
HT 是啥:Everything you need to create cutting-edge 2D and 3D visualization. 这口号是当年心目中的产品方向,接着就朝这个方向慢慢打 ...
- 我心中的核心组件(可插拔的AOP)~消息组件~完善篇
回到目录 为什么要有本篇文章 本篇文章主要实现了RTX消息生产者,并且完成了整体的设计方式,之前在设计时消息生产者全局使用单一的生产方式,即一个项目里使用了Email就不能使用SMS,这种设计方法和实 ...
- ActiveX控件(ATL篇)
目录 第1章 VC++6.0创建 2 1.1 目标 2 1.2 创建项目 2 1.3 增加COM类 4 1.4 属性 7 1.5 事件 8 1.6 实现连接点 ...
- Bootstrap组件福利篇:十二款好用的组件推荐
阅读目录 一.时间组件 1.效果展示 2.源码说明 3.代码示例 二.自增器组件 1.效果展示 2.源码说明 3.代码示例 三.加载效果 一.实用型 二.炫酷型 四.流程图小插件 1.效果展示 2.源 ...
- UI2CODE智能生成代码——组件识别篇
1.背景 在<UI2CODE——整体设计篇>中,我们介绍了UI2CODE工程的整体流程: 在组件识别这个环节,需要有一种处理布局信息的方法,来解析和计算控件间的布局关系(比如识别业务组件( ...
- 【Flutter组件终结篇】332个组件 658页PDF
老孟导读:历时1年的时间,整理完成了330+组件的详细用法,不仅包含UI组件,还包含了功能性的组件. 虽然整理了 330+的组件基本用法,但并不是让你每一个都学习一遍,任何技术基本都是掌握 20%就可 ...
- Angular2开发拙见——组件规划篇
本文集中讲讲笔者目前使用ng2来开发项目时对其组件的使用的个人的一些拙劣的经验. 先简单讲讲从ng1到ng2框架下组件的职责与地位: ng1中的一大特色--指令,分为属性型.标签型.css类型和注释型 ...
随机推荐
- 使用JavaScript操作DOM节点元素的常用方法(创建/删除/替换/复制等)
getElementById(id)这是通过id来访问某一元素,最常用的之一,例:<html><body><div id="myid">test ...
- centos6.6 设置静态网络
[root@localhost ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0HWADDR=08:00:27:3D:5F:38 ...
- vs2012 提示 未能正确加载 "Visual C++ Language Manager Package" 包 的解决办法
1.点击vs2012菜单栏 工具-> Visual Studio 命令提示 打开命令窗口 2.输入命令 "devenv /Setup" 3.重新打开vs2012
- chmod 无法修改磁盘文件的权限解释 (光盘文件就是只读的,修改不了的)
我们知道root用户是linux执行权限最高的管理者用户,他可以进行任何的权限操作:然而我们的操作系统同样也考虑过这样的弊端,就是当我们使用者并不了解文件属性和重要性时会给予我们使用者提示: 举个例子 ...
- String一点小发现
今天面试官问了几个关于java内存方面的问题,其中有一个是关于内存重复使用的.突然想到java中String比较特殊的地方,根据自己的理解所以稍微记录一下以免遗忘. 对于下面这个小程序: public ...
- django-crontab定时任务
django-crontab实现定时任务 1 django-crontab安装 django-crontab安装: django-crontab加入:只需要将INSTALLED_APPS即可.如下代码 ...
- JAVA排序--[快速排序]
package com.array; public class Sort_Quick { /* * 项目名称:快速排序 ; * 项目要求:用JAVA对数组进行排序,并运用快速排序算法; * 作者:Se ...
- [Effective Java]第九章 异常
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- Windows Internals学习笔记(四)Trap Dispatching
参考资料: 1. <Windows Internals> 知识点: ● 陷阱trap:它是一种处理器机制,用以在某一异常或中断出现时,捕捉该执行线程,并将其控制权转交到操作系统中某一固定位 ...
- C++指针内存
这是一个关于C++指针的问题,思考了一下 void GetMemory(char *p, int num){ p = (char*) malloc (sizeof(char) * num); } vo ...