一、COM简介1

1.COM是微软组件对象模型检测,由于COM具有二进制代码共享特性,所以它具备

高可开发性,高度可维护性,和高度可移植性,以至于Winows很多软件都采用COM

做整体架构,比如微软DirectX等,COM流行于2000-2004,由于它的普及面广,

应用繁多,加上Windows对齐默认支持,开发出的软件无需依赖其他开发包.

所以被很多开发公司采用, 坐位一个VC++程序员,是否掌握COM用法

称为是否合格的表格指标.

2.COM是一门深邃的思想和技术.要想完全掌握的话,没有半年是很难做到的.

3.优点:采用COM组件架构我们的软件,可以使已编写好的功能模块可以

很方便的移植到其他平台比如C++的MFC平台移植到C#的WinForm平台

因为COM组件是夸应用的,可以被C++调用,也可以被C#调用

二、COM接口与QueryInterface

1.现实中的组件和接口

a) 一个手机,一个MP3,一个充电宝,那么充电宝的作用就是给手机充电,

充电宝上有一个接口的USB的,有一根数据线连接到手机上,给手机充电

b) 手机充完电后, 把线接到MP3上,这时候就给MP3充电了.

c) 这3个物件中:手机本身是一个组件,MP3也是一个组件,充电宝也是组件。

因为他们都具备可独立性,

组件和组件通过什么连接呢? 就是通过一个公用的USB接口.进行沟通.

d) 接口的定义:接口是组件和组件之间进行交换的,

CPU内存条这些有固定的接口,因此你更换CPU的时候也必须要相同接口的CPU.

主板不直接识别CPU,而是通过那个接口来识别CPU。

e) 接口的协议确定好后往往是不能再改变了,比如五号电池不能做的大,也不能小.

2.C++程序中的组件与接口

定义接口:

#define interface struct

在c++中interface其实就是struct

定义两个接口

interface OPEN

{

virtual void OPENOK()=0;

virtual voud OPENERROR()=0;

}

interface CLOSE

{

virtual void CLOSEOK()=0;

virtual voud CLOSEERROR()=0;

}

定义组件 组件是派生与接口的,

class BES : public OPEN,public CLOSE

{

public:

//实现接口....

};

BES* b = new BES();//组件实例

OPEN* t = b;//获取接口

t->OPENOK();//调用接口

//组件第二个接口

CLOSE* c = b;//获取接口

t->CLOSEOK();//调用接口

组件可以有多个接口, 这些接口又有不同的功能

销毁组件 delete

3.COM组件与接口

a) COM组件通过二进制代码共享实现跨应用,比如应用A的COM组件

的可以直接把这个COM组件拿到应用B来用(开发)

b)class类文件源码这些就是普通的源码共享,COM是二进制共享方式.

c) COM组件完全与变成语言无关的,可以被VC调用,可被网页调用,可被.net调用

d) COM组件只能运行在Windows平台,不能再Linux和苹果机上面运行.

e)

IUnknow接口 声明

interface IUnknown

{

virtual HRESULT QueryInterface(const IID&iid,void** ppv)=0;

virtual ULONG AddRef()=0;

virtual ULONG Release()=0;

}

5.QueryInterface函数,与HRESULT类型,IID类型,数据类型转换

----- QueryInterface函数

a) 查询某个组件是否支持特定的接口,比如说上面的BES组件他有两个接口

我想要知道BES组件是否支持其他的接口,我在外部是不知道你支持还是

不支持的,所有通过QueryInterface来查询接口知道你是否支持这个接口.

b) 返回结果是通过第二个参数输出的,你把组件指针传进去,不为NULL就是找到接口.

c)返回值HRESULT

S_OK 成功

S_FALSE 函数成功执行完成,但返回出现错位

E_INVALIDARG 参数有错误

E_OUTOFMEMORY 内存申请粗我

E_UNEXPECTED 未知异常

E_NOTIMPL 未实现的功能

E_FAIT 没有详细说明的粗我

E_POINTER 无效的指针

E_HANDLE 无效的句柄

E_ABOUT 终止操作

E_ACCESSDENIED 访问被拒绝

E_NOINTERFACE 不支持接口

-----IID

IID是接口表示符,Interface ID ,每个接口都可以设置一个接口标识符

用来标志这个接口,标志了某个接口之后IID的值是不能再修改的,

GUID定义

typedef struct _GUID

{

DWORD D1;//随机数

WORD D2; //和时间有关

WORD D3; //和时间有关

BYTE D4[8]; //和网关MAC相关

}GUID

GUID生成方法 在VS工具里有一个创建GUID

理论上将GUID是不可能重复的,重复可能性非常小,每秒钟一万亿个GUID的情况下

即使太阳变成白矮星,他也是唯一的.

("40125064-D4C6-4165-8535-72D35FE44D21")

GUID这样定义的 用逗号分隔

static const GUID guid = 
{

0x40125064,

0xD4C6,

0x4165,

{

0x85,

0x35,

0x72,

0xD3,

0x5F,

0xe4,

0x4d,

0x21

}

}

在编辑器里这个就表示一个接口标识符,它是固定的.

注意我说的不是图片里的固定,

而是你自己去生成的, 我这个只是一个示范.

6.接口继承自IUnknown

然后组件实现IUnknown接口里的函数

QueryInterface实现

    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid,void**ppv){//ppv返回的接口指针 0就是没有找到该接口if(iid == IID_IUnknown){//即使CPD 继承两个IUnknown接口,其中一个是OPEN//另一个是CLOSE //直接防护当前这个指针*ppv = (IID_OPENS*)this;}else if(iid == IID_OPEN_KEY) //对比唯一的GUID接口标识符{*ppv = (IID_OPENS*)this;}else if(iid == IID_CLOSE_KEY){*ppv = (IID_CLOSE*)this;}else{//查询不到IID *ppv返回NULL*ppv = NULL;//返回E_NOINTERFACE 表示组件没有该接口(不支持这个接口)return E_NOINTERFACE; }return S_OK;}

组件调用该函数,查询这个组件是否支持该接口

   //实例化组件CPD* p = new CPD();IUnknown* pkonw = NULL;HRESULT hr;//从组件查询UInknow组件hr = p->QueryInterface(IID_IUnknown,(void**)&pkonw);if(SUCCEEDED(hr)) //对HRESULT返回值判断 一般用SUCCEEDED{//然后从IUnknown查询 OPEN接口IID_OPENS* op  = NULL;hr = pkonw->QueryInterface(IID_OPEN_KEY,(void**)&op);if(SUCCEEDED(hr)) {//调用接口的方法op->Open();}}delete p;

判断两个接口是否相同

if((void*)接口指针1 != (void*)接口指针2)

{

两个接口不同

}

三、引用计数 AddRef和Release

1.内存资源何时释放

组件 = nwe 组件

然后delete 组件,这样就销毁一个组件了

但是把接口传给组件成员变量

组件 = new 组件(接口指针变量)

怎么才能知道什么时候不用这个组件

在main主函数最后面执行delete组件,销毁???

主函数最后面销毁组件实例,可行,但不是一个好办法

因为这样最终是释放组件实例的内存资源,不过却不是

即时(在实例所指组件不用时)地释放内存资源,

这个程序在运行中,占内存将是巨大的

解决这个问题需要用到引用计数技术.

2.引用计数原理

a) 引用计数就是用啦管理对象声明周期的一种技术

b) 对象O可能被外界A,外界B,外界C引用

也就是说A,B,C都在使用这个对象O

c) 每次外界对象引用这个对象,计数器就+1

每次外界不用对象时,计数器减1

d) 在计数值为0时,执行delete this销毁自己的资源.

e) 引用计数使得对象通过引用计数能够知道何时对象

不再被使用,然后及时地删除自身所占的内存资源

f) IUnknown接口的AddRef与Release就是引用计数实现方式

3.AddRef与Release实现与使用

类里有一int类型的变量在构造函数里初始化为0;

他就是引用计数器,然后构造函数调用AddRef引用计数+1

virtual ULONG STDMETHODCALLTYPE AddRef(){return m_Icount++; }

Release实现

virtual ULONG STDMETHODCALLTYPE Release()

{

if(--m_Icount == 0)

{

delete this;

return 0;

}

return m_Icount;

};

如果接口不再调用必须手动调用Release

再赋值后也要调用AddRef()

转载于:https://blog.51cto.com/12158490/2105117

COM技术入门(1)相关推荐

  1. 《Docker技术入门与实战》——2.4 本章小结

    本节书摘来自华章计算机<Docker技术入门与实战>一书中的第2章,第2.4节,作者:杨保华,戴王剑,曹亚仑著, 更多章节内容可以访问云栖社区"华章计算机"公众号查看. ...

  2. python编程入门与案例详解pdf-Flutter技术入门与实战 PDF 清晰版

    给大家带来的一篇关于Flutter相关的电子书资源,介绍了关于Flutter入门.Flutter实战.Flutter技术方面的内容,本书是由机械工业出版社出版,格式为PDF,资源大小162.5 MB, ...

  3. 《Docker技术入门与实战》——2.3 本书环境介绍

    本节书摘来自华章计算机<Docker技术入门与实战>一书中的第2章,第2.3节,作者:杨保华,戴王剑,曹亚仑著, 更多章节内容可以访问云栖社区"华章计算机"公众号查看. ...

  4. 《SaltStack技术入门与实践》—— Job管理

    Job管理 本章节参考<SaltStack技术入门与实践>,感谢该书作者: 刘继伟.沈灿.赵舜东 在SaltStack里面执行任何一个操作都会在Master上产生一个jid号.Minion ...

  5. 【Zigbee技术入门教程-02】一图读懂ZStack协议栈的核心思想与工作机理

    [Zigbee技术入门教程-02]一图读懂ZStack协议栈的核心思想与工作机理 广东职业技术学院  欧浩源   Z-Stack协议栈是一个基于任务轮询方式的操作系统,其任务调度和资源分配由操作系统抽 ...

  6. 《 Docker 技术入门与实战 》读书笔记 ( CentOS 安装 Docker )

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. PS :个人所有读书笔记只记录个人想要的内容,很可能原书大量内容没有纳入笔记中... ... 以下全 ...

  7. android hook底层代码_Java-Hook技术-入门实践(反射、动态代理)-Hook拦截通知(当前App/Context)...

    老样子,上一篇MonkeyLei:Java-Hook技术-入门实践+反射.动态代理.热修复再看看 我们Hook学习了一下,一个是Java本地Main的实践练习. 一个是Android的监听事件的Hoo ...

  8. 赞一个 kindle电子书有最新的计算机图书可买了【Docker技术入门与实战】

    最近对docker这个比较感兴趣,找一个比较完整的书籍看看,在z.cn上找到了电子书,jd dangdang看来要加油啊 Docker技术入门与实战 [Kindle电子书] ~ 杨保华 戴王剑 曹亚仑 ...

  9. 射频和无线技术入门--传统技术--7

    射频和无线技术入门--传统技术--7 1.广播 1.1 广播的概念 1.1.1 特性 1.1.2 约束 1.2 频率的角色 1.2.1 分配 1.2.2 传播 1.3 调谐 1.3.1 调谐器 1.4 ...

  10. 新课发布-SpringBoot2.0缓存中间件Redis技术入门与实战(抢红包系统设计与实战)

    概要介绍:历经半个多月的时间,Debug呕心沥血.亲自录制的 "缓存中间件Redis技术入门与应用场景实战(SpringBoot2.x + 抢红包系统设计与实战)"的新课终于完成了 ...

最新文章

  1. 多线程pthread_join()的作用
  2. pku 1185 炮兵阵地
  3. Java获取近七天的数据条数,及页面实现折线图(附前后端代码)
  4. 趣学python3(30)-字典
  5. unity中单位是米还是厘米_401场地清理是什么,由施工单位做还是甲方做?造价中如何体现?...
  6. Red5 webapp配置
  7. 解决:Error response from daemon: Get https://index.docker.io/v1/search?q=openjdkn=25: dial tcp: looku
  8. Problem C: 顺序表基本运算(线性表)
  9. 栈的应用c语言计算器思路,请问,用c语言做一个计算器 包括+-*/()的运算 用栈 该怎么做...
  10. idea中build project不能用_Java语言编程第40讲——如何在一个项目中组织多个SpringBoot服务
  11. 基于Verilog HDL的数字秒表
  12. 巧用Q盘搭建SVN服务器
  13. 笔记本计算机提升性能,笔记本电脑改装!轻松提升电脑性能!
  14. QScrollArea使用教程之实现可上下滑动的设置界面
  15. 有一个棋盘,有64个方格,在第一个方格里面放1粒芝麻重量是0.00001kg,第二个里面放2粒,第三个里面放4,棋盘上放的所有芝麻的重量。
  16. Python/用 Pgzrun 库做一个简单小游戏
  17. Linux ARM平台开发系列讲解(GMSL摄像头篇)1.1 GMSL协议介绍
  18. Netty面试题(史上最全)
  19. 详解CSRF跨站点请求伪造
  20. word密码忘了怎么解开

热门文章

  1. 27.用webpack自搭react和vue框架
  2. 'telent' 不是内部或外部命令,也不是可运行的程序或批处理文件。
  3. EasyPusher直播推送中用到的缓冲区设计和丢帧原理
  4. 概率论与数理统计图解
  5. android架构图示
  6. HTML sublime :Please wait a bit while PyV8 binary is being downloaded 及代码和注释颜色 ,大小调节
  7. JavaScript基础流程控制(3)
  8. python学习之路——day1(18/9/11)
  9. MyBatis 拦截器 (实现分页功能)
  10. centos 安装图形桌面