1. 基础介绍

组件对外公布的是接口;一个组件可以实现多个接口,也就是说可以对外公布多个接口,你很少会100%的去完全了解一个组件的所有接口,就像你去学习编程一样,你几乎不可能去成为编程中的全才。那么,既然我们不能去完全的了解一个组件提供的所有接口,那么我们在实际开发中,如何去判断一个组件是否提供对应的接口呢?看文档?是的,是个好主意,在文档的海洋,找到一个知识点,真的很难,浪费时间和精力;其实,组件本身就提供对自己查询的一个接口,让客户去询问组件,问它是否支持某个接口,在经过多次的这种询问之后,客户对于组件的认识将越来越清晰。

2. IUnknown

上面说到组件本身提供一个对自己查询的接口,那么这个接口是什么呢?这就是大名鼎鼎的IUnknown接口了,IUnknown接口在Windows SDK的unknwn.h中定义,它的定义如下:

interface IUnknown
{public:virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, _COM_Outptr_  void **ppvObject) = 0;virtual ULONG STDMETHODCALLTYPE AddRef( void) = 0;virtual ULONG STDMETHODCALLTYPE Release( void) = 0;
};

这里的STDMETHODCALLTYPE表示调用方式,也就是windows API的__stdcall方式。可以看到,在IUnknown中定义了一个名为QueryInterface的函数。客户可以调用QueryInterface来判断组件是否支持某个特定的接口,而对于剩下的AddRef和Release两个接口操作,会在之后进行总结。

所有的COM接口都需要继承IUnknown接口;因此,如果某个客户拥有一个IUnknown接口的指针,它并不需要知道它所拥有的接口指针到底是指向什么类型的,而只需要知道此接口可以用来查询其它接口就行了。

由于所有的COM接口都首先继承了IUnknown,所以每个接口的vtbl中的前三个函数都是QueryInterface,AddRef和Release。这就使得所有的COM接口都可以被当成IUnknown接口来处理。如果某个接口的vtbl中的前三个函数不是这三个,那么它将不是一个COM接口。由于所有的接口都是从IUnknown继承而来的,因此所有的接口都支持QueryInterface。所以,组件的任何一个接口都可以被客户用来获取它所支持的其他接口。由于所有的接口指针同时也将是IUnknown指针,客户并不需要单独维护一个代表组件的指针,它所关心的将仅仅是接口的指针。

既然,我们可以只用QueryInterface去询问组件是否支持某个接口,但是,这一切都是基于获得了IUnknown接口指针之后,才能进行的操作,那么如何获得一个指向组件的IUnknown接口指针呢?我们可以实现一个CreateInstance函数,它建立一个组件并返回一个IUnknown指针;对于客户来说,可以调用CreateInstance获得IUnknown指针,而不用使用new操作符了。在系统的总结了COM的所有基础知识之后,我再说说系统提供的一个创建组件实例的API函数。

3. QueryInterface

3.1 QueryInterface介绍

IUnknown中包含一个名为QueryInterface的成员函数,客户可以通过此函数来查询某个组件是否支持某个特定的接口。
若支持,QueryInterface将返回一个指向此接口的指针;否则返回值将是一个错误代码;然后客户可以接着查询其它接口。

从QueryInterface函数的声明中可以看出,QueryInterface有两个参数:
第一个参数标识客户所需的接口,这个参数是一个接口标识符(IID)结构;
第二个参数用来存放所请求的接口的地址。
QueryInterface返回的是一个HRESULT值,它是一个具有特定结构的32位值;对于返回的HRESULT值,在实际开发中,需要使用SUCCEEDED宏或FAILED宏去进行判断HRESULT值是表示成功还是失败。

3.2 QueryInterface简单实现

总结了QueryInterface的简单实现,说白了,就是简单工厂模式的实现;上面也说了,就是根据客户提供的IID接口标识符,然后获得对应的接口的指针,返回对应的接口的指针;如果组件支持客户指定的接口,那么应返回S_OK以及相应的指针;若不支持,返回值应是E_NOINTERFACE,并将相应的指针返回值置成NULL。下面通过一个简单的例子来说明QueryInterface的简单实现:

比如有上述的一个结构;接口IX和IY都继承自IUnknown接口,组件CA实现了IX和IY接口,那么QueryInterface的实现应该像下面这样:

HRESULT __stdcall CA::QueryInterface(const IID &iid, void **ppv)
{if (iid == IID_IUnknown)*ppv = static_cast<IX *>(this);else if (iid == IID_IX)*ppv = static_cast<IX *>(this);else if (iid == IID_IY)*ppv = static_cast<IY *>(this);else{*ppv = NULL;return E_NOINTERFACE;}static_cast<IUnknown *>(*ppv)->AddRef();return S_OK;
}

3.3 QueryInterface的简单使用

当我获得了一个IUnknown指针以后,就可以调用对应的QueryInterface进行查询了,如下:

void Fod(IUnknown *pI)
{IX *pIX = NULL;// Ask for interface IXHRESULT hr = pI->QueryInterface(IID_IX, (void **)&pIX);// Check the return valueif (SUCCEEDED(hr)){// Use the interfacepIX->Fx();}
}

4. COM编程——IUnknown介绍相关推荐

  1. 计算机 编程 教程 pdf,计算机专业教程-第3章编程接口介绍.pdf

    下载 第3章 编程接口介绍 • DB2 UDB应用程序概述 • 嵌入S Q L编程 • CLI/ODBC应用程序 • JAVA应用程序 • DAO .R D O .A D O应用程序 本章将介绍对DB ...

  2. java面向方面编程_面向方面编程的介绍----基本概念

    面向对象的编程中常用的概念是:继承.封装.多态.在面向方面的编程中常使用的概念是:advices/interceptors, introductions, metadata, and pointcut ...

  3. 编程关键词介绍...

    编程关键词介绍: gcc是GUN compiler Collection (GUN编译器套件),也可以简单理解为编译器,他可以编译多种语言. GNU是基于Unix开发设计,并且是与Unix兼容的操作系 ...

  4. 输入2个正整数lower和upper(lower_题库 | 华为研发工程师编程题型介绍及解析 第 2 期...

    题目1:给定两个已经升序排序好的的序列 A={a1,a2,a3,-an} 和 B={b1,b2,b3-bn} ,一个数 R,找出满足以下条件的的(ai,bj)序列对. 1.ai<=bj 2.bj ...

  5. pythonguitkinter编程入门_Python Tkinter GUI编程入门介绍

    一.Tkinter介绍 Tkinter是一个python模块,是一个调用Tcl/Tk的接口,它是一个跨平台的脚本图形界面接口.Tkinter不是唯一的python图形编程接口,但是是其中比较流行的一个 ...

  6. OpenCV 编程简单介绍(矩阵/图像/视频的基本读写操作)

    PS. 因为csdn博客文章长度有限制,本文有部分内容被截掉了. 在OpenCV中文站点的wiki上有可读性更好.而且是完整的版本号,欢迎浏览. OpenCV Wiki :<OpenCV 编程简 ...

  7. abb机器人离线编程软件叫做_工业机器人离线编程(ABB)1-2 常用离线编程软件介绍.pptx...

    1-2 常用离线编程软件介绍;一.常用离线编程软件;1. ABB RobotStudio离线编程软件介绍RobotStudio 是一款 PC 应用程序,用于机器人单元的建模.离线创建和仿真.如图1-1 ...

  8. 幼儿机器人编程课程介绍

    幼儿机器人编程课程介绍?对于很多的家长们来说,孩子的学习一直都是他们十分关心和重视的一件事情.很多的家长在培养孩子的学习的时候,也可以说是十分的耐心的.他们会给孩子选择一些能够对于孩子学习有帮助的课程 ...

  9. 朱有鹏 socket编程接口介绍(3)

    朱有鹏 socket编程接口介绍(3) 建立连接 socket(man 2 socket) socket()函数类似于open()函数,用来打开一个网络连接,如果成功则返回一个网络文件描述符(int类 ...

  10. Motoman机器人离线编程——MotocomES介绍

    欢迎关注Jungle的Motoman机器人离线编程专栏系列文章: Motoman机器人离线编程--Motocom32开发简介 Motoman机器人离线编程--Visio Studio环境配置 Moto ...

最新文章

  1. python key lambda_使用“key”和lambda表达式的python max函数
  2. flock - 必应词典
  3. 微信小程序中this指向作用域问题this.setData is not a function报错
  4. Angular 项目中的可摇树依赖 - Tree-shakable dependencies
  5. 重新加一个window_Activity、View、Window关系,进程间通信,责任链模式,Https,数据存储...
  6. Prometheus监控学习笔记之360基于Prometheus的在线服务监控实践
  7. git如何切换用户_git切换用户、多用户切换的正确方式 git commit和git push 切换用户...
  8. HDU1799 循环多少次?
  9. 如何让背景图片固定在中间,滚动内容图片不动?
  10. 编写你的第一个Django应用程序
  11. python实现微信打飞机
  12. 基于R语言的聚类(谱聚类)
  13. mac系统ps快捷键大全-来自三人行慕课
  14. Windows 10 合并磁盘分区 (G and H)
  15. 聚焦手机操作系统 运营商的“门户”之战
  16. linux系统管理及配置
  17. 前10节的理解和总结
  18. 颜色混合BlendFunc用法实例总结
  19. 183day(Lambda表达式了解)
  20. C/C++ 的平方和开平方函数

热门文章

  1. 25年面试官首次揭秘——世界500强面试题之微软面试题
  2. 工作以后就不怎么想学习了
  3. 一起谈.NET技术,ASP.NET MVC Routing概述
  4. 如何购买微软的wince 等授权组件等?(找到了!)
  5. C#中唯一的三元运算符
  6. ajax清除session,跳出iframe框架页面后跳转页面
  7. GIT每次上传代码都必须输入用户名解决方案
  8. ELK 收集多个日志文件
  9. No package ‘glib-2.0‘ found/No package ‘gobject-2.0‘ found
  10. 电脑坏了,疑似主板故障