• COM组件开发


    前言

    在COM规范中,最基本的两个要素就是对象与接口,因为COM就是由这两者来共同实现的。COM对象在组件中是被封装起来的,客户代码只能通过接口来访问COM对象并享受其服务,由于客户与COM直接打交道的是COM接口,所以COM接口是COM最关键的要素。

    COM是什么

    COM是一种跨应用和语言共享二进制代码的方法。
    Windows使用DLLs在二进制级共享代码。这也是Windows程序运行的关键――重用kernel32.dll, user32.dll等。但DLLs是针对C接口而写的,它们只能被C或理解C调用规范的语言使用。由编程语言来负责实现共享代码,而不是由DLLs本身。这样的话DLLs的使用受到限制。
    MFC引入了另外一种MFC扩展DLLs二进制共享机制。但它的使用仍受限制――只能在MFC程序中使用。
    COM通过定义二进制标准解决了这些问题,即COM明确指出二进制模块(DLLs和EXEs)必须被编译成与指定的结构匹配。这个标准也确切规定了在内存中如何组织COM对象。COM定义的二进制标准还必须独立于任何编程语言(如C++中的命名修饰)。一旦满足了这些条件,就可以轻松地从任何编程语言中存取这些模块。由编译器负责所产生的二进制代码与标准兼容。
    在内存中,COM对象的这种标准形式在C++虚函数中偶尔用到,所以COM代码大都使用C++语言,但是必须要记住的是编写模块用的语言无关,产生的二进制代码是所有语言都可用的。

    COM对象

    COM对象其实就类似于C++中的对象,也就是说某个类的实例,包含了一组数据和操作。在COM模型中,COM对象的位置对于客户来说是透明的,即客户代码不需要直接初始化一个COM对象,而是COM库通过一个全局标识码GUID去对其进行初始化工作。GUID是一个128位的标识符,基本保证了COM对象的唯一性,另外COM接口也是用GUID来标识的。
    COM对象的封装特性与C++的封装特性有所不同,COM对象的成员数据是以组件模块为边界,对于客户代码来说是看不见的,只能通过接口的函数去访问属性;而C++对象的封装特性则是语义上的封装,对于客户代码来说是可见的。

    COM与C++可重用性对比

    COM对象的可重用性在表现在聚合与包容,使得一个对象可以完全使用另一个对象的所有功能;而C++的重用性表现在继承上,则子类对象完全继承父类对象的属性与方法。COM对象的重用主要是对象本身的重用,体现在模块之间;而C++对象则更多通过继承来实现源代码级的重用,体现在模块内部。

    COM与C++多态性对比

    C++的多态性是其面向对象特性中最重要的一环,它是通过虚函数的机制来实现的。而COM对象也具有多态性,它是通过COM接口来实现的,即一个COM允许一个对象同时实现多个接口,因此,一个COM对象的多态性是由其接口实现的。

    COM接口及其特性

    COM接口通常是一组以函数的逻辑集合,其命名一般以“I"为前缀,并且继承IUnKnown接口。COM对象可以提供多个COM接口,每个接口提供不同的服务,因此COM接口与COM对象一样,都是用GUID来标识的,客户通过GUID来获取接口指针,再通过接口指针获取对应的服务。
    COM接口规范并不建立在任何编程语言的基础上,而是在二进制一级的标准,任何语言只要有足够的表达能力对接口进行描述即可开发COM的应用。
    COM接口是客户与COM对象之间的桥梁,其重要性不言而喻,若接口总是变化,会使客户代码也跟着变化,这对于应用的开发是很不利的,所以接口一般是不变的。
    多态是OOP的重要特点,对于COM来说也一样,而COM对象的多态性是通过COM接口的多态来体现的。

    IUnknown接口

    接口IUnknown的定义:

    class IUnknown{  
    public:  
        virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) = 0;  
        virtual ULONG __stdcall AddRef() = 0;  
        virtual ULONG __stdcall Release() = 0;  
    

    };

    IUnknown接口是COM的核心,因为所有其他的COM接口都必须从IUnknown继承。它包含三个接口函数:QueryInterface()、AddRef()和Release(),其中QueryInterface()用于接口查询,从COM对象的一个接口获得另一个接口,一个对象可能实现了多个接口,这样就可以通过QueryInterface()在对象多个接口之间跳转从而获得多个接口提供的服务;AddRef()与Release()则用于管理COM对象的生命周期,当COM对象不再使用时需要释放,因此COM使用了引用计数的方法来对对象进行管理,当有一个用户获得接口指针后调用AddRef()将引用计数加1,相反,当一个用户用完接口指针后就调用Release()来使引用计数减1,这样当引用计数为0时,COM对象就可以从内存中释放。由于IUnknown提供了接口查询与生命周期控制两个功能,因此COM的每个接口都应该继承于它。

  • 相关阅读:
    CSDN如何能实现直接粘贴把图片上传到服务器中
    Blog如何能实现直接粘贴把图片上传到服务器中
    博客如何能实现直接粘贴把图片上传到服务器中
    wordpress如何能实现直接粘贴把图片上传到服务器中
    CMS如何能实现直接粘贴把图片上传到服务器中
    html+Nginx超大视频上传解决方案
    《TrustZone for Armv8-A》阅读笔记
    《ARM Trusted Firmware》阅读笔记
    《Linux/Unix系统编程手册》 第29章 线程:介绍
    《Linux/UNIX系统编程手册》第28章 详述进程创建和程序执行
  • 原文地址:https://www.cnblogs.com/308cww/p/7788652.html
Copyright © 2020-2023  润新知