当前位置:  编程技术>c/c++/嵌入式

C++ COM编程之QueryInterface函数(一)

    来源: 互联网  发布时间:2014-10-29

    本文导语:  前言 组件对外公布的是接口;一个组件可以实现多个接口,也就是说可以对外公布多个接口,之前也总结过了,你很少会100%的去完全了解一个组件的所有接口,就像你去学习编程一样,你几乎不可能去成为编程中的全才。那...

前言

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

关于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,再根据对之前的文章COM编程——接口的背后 的理解,我们可以知道每个接口的vtbl中的前三个函数都是QueryInterface,AddRef和Release。这就使得所有的COM接口都可以被当成IUnknown接口来处理。如果某个接口的vtbl中的前三个函数不是这三个,那么它将不是一个COM接口。由于所有的接口都是从IUnknown继承而来的,因此所有的接口都支持QueryInterface。所以,组件的任何一个接口都可以被客户用来获取它所支持的其他接口。由于所有的接口指针同时也将是IUnknown指针,客户并不需要单独维护一个代表组件的指针,它所关心的将仅仅是接口的指针。

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

关于QueryInterface

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

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

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(this);
     }
     else if (iid == IID_IX)
     {
          *ppv = static_cast(this);
     }
     else if (iid == IID_IY)
     {
          *ppv = static_cast(this);
     }
     else
     {
          *ppv = NULL;
          return E_NOINTERFACE;
     }
     static_cast(*ppv)->AddRef();
     return S_OK;
}

QueryInterface的简单使用

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

代码如下:

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

完整的例子

上面说了那么多了,现在提供一个完整的例子,将上面的各种理论知识都在实际代码中进行了实践,让各位能更好的理解QueryInterface。(下载)。

总结

QueryInterface理解起来比较简单,但是,它的理论知识还是必须要去掌握的,理论是一切的基础,没有理论作为支撑,任何实际的操作都不会那么可靠和可信,所以,这篇文章总结的偏于理论多一些。由于QueryInterface部分的内容比较多,使用一篇文章无法总结的齐全,所以,之后我还会继续总结关于QueryInterface的第二部分。


    
 
 
 
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • 哪位大侠有python的win32com的api函数说明?
  • .NET下 c#通过COM组件操作并导出Excel实例代码
  • sendmail如何配置多个邮件域名,在局域网内 如 aaa@aaa.com;aaa@bbb.com,
  • 我编一个程序要控制端口Com1,但手头没有那个设备,谁知道哪里有能模拟Com端口的软件!!!!!!
  • 关于apache ,端口该为8080,想http://www.as.com访问,而不是www.as.com:8080
  • import com.sun.java.swing.*;提示找不到com.sun.java包我该怎么办?急!
  • com.borland.dbswing.* 在什么文件里啊?可以发给我一个吗?Rex_fa@163.com 告诉我也行
  • 谁知道类似于my.sina.com.cn和cn.my.yahoo.com中的版面个性化定制的原理是什么?
  • 比如进入a.com,怎么自动过3秒转入bb.com?
  • com.Oracle.*;是指相对于当前目录下的COM下的ORACLE吗?java是怎么寻找PACKAGE的?
  • ###java调用COM组件或COM调用java组件(EJB)解决办法。###
  • Foursquare.com的客户端 Foursquare
  • 便携软件套装 PortableApps.com
  • Use COM in java
  • Java能否写COM组件?
  • 怎么去配置COM口?
  • 多媒体叠加COM组件 ansoply
  • DNS问题 http://ooo.com 不能访问
  • java如何调用com?
  • 我的代码中已经假如smtp认证,为什么在tomcat上还提示客户端没有验证?使用smtp.sohu.com或smtp.sina.com.cn都不行代码如下:
  • 有谁能给我电子白板的源代码???急!!!!!!guangmin001@china.com
  • 不解决也给分。com1连机很慢?


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3