一场因为想偷懒引发的那些事——COM的那些事1

参考&&引用

The layout of a COM object

Adjustor thunks

What Is a COM Interface?

起因

看来人总是健忘的,只能隐约的记得是因为一个关于C#封装的COM接口的问题。于是自己动手封装实现了一下,接着就引发了下面一系列的问题。
一场因为想偷懒引发的那些事——COM的那些事1
一场因为想偷懒引发的那些事——COM的那些事2
一场因为想偷懒引发的那些事——WinDbg的简单用法
一场因为想偷懒引发的那些事——记C# Com接口调用的相关姿势
一场因为想偷懒引发的那些事——C#调用COM的一个进阶使用方式
一场因为想偷懒引发的那些事番外——结构体的一些事

一些引子

COM(Component Object Model)一个Winodws在很久之前提出的用于不同应用之间的组件复用模型,简单来说COM有点像C#里的interface。
不同应用不管用的是C、C++、Java、C#,不用知道这个组件的具体实现,只需要知道这个接口约定,就可以调用该组件。

虽说现在有各种复用的方式,但是想想COM的提出是在C++都还没开始流行的时代,感觉挺厉害的!😏

在Windows编程中有不少的功能都会或多或少的与COM打交道,例如:

  • 图形(Direct2D)
  • Windows Shell(Windows桌面、资源管理器)
  • UI animation
  • UI Automation

关于如何使用COM Interface 有很多种姿势,包括不限于:传统的(C++中使用相关头文件、C#中使用相关封装好的库)、ps:算是躺着用。

进阶的(C#中手动使用P/Invoke 调用COM,虽说封装着麻烦,但是个性化定制较好)ps: 算是站着用。

另外还有一种比较另类的姿势:找到拿到内存地址,直接找到虚函数表,然后计算偏移量,最后调用相关函数。就好像日常便饭吃腻了,偶尔换换新口味,这个方式可以满足不想受限于常规调用的方式,就暂称为XX调用吧(这个XX呢根据每个人理解有不同含义,有些人认为吃力不讨好、有些人呢就认为是装那个高大上、还有的呢认为脑子可能多半坏了)

这个XX姿势在使用前呢,需要了解一下COM的基本知识,不然遇到问题都不知道从何入手。于是接下来就是本篇要说的内容了——COM对象的内存布局。

正文

Win32 COM调用规范指定了对象虚函数表(vtable)的布局结构,并且Win32 COM 对象的布局和C++的对象布局十分的相似,例如:上述引用中所说的一个IPersist这个COM 对象,其C风格的定义如下(从ObjIdl.h中复制粘贴来的源码):

/* C style interface */

    typedef struct IPersistVtbl
    {
        BEGIN_INTERFACE
        
        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( 
            __RPC__in IPersist * This,
            /* [in] */ __RPC__in REFIID riid,
            /* [annotation][iid_is][out] */ 
            _COM_Outptr_  void **ppvObject);
        
        ULONG ( STDMETHODCALLTYPE *AddRef )( 
            __RPC__in IPersist * This);
        
        ULONG ( STDMETHODCALLTYPE *Release )( 
            __RPC__in IPersist * This);
        
        HRESULT ( STDMETHODCALLTYPE *GetClassID )( 
            __RPC__in IPersist * This,
            /* [out] */ __RPC__out CLSID *pClassID);
        
        END_INTERFACE
    } IPersistVtbl;
//这里的interface是一个宏定义,定义为另一宏__STRUCT__即struct
    interface IPersist  
    {
        CONST_VTBL struct IPersistVtbl *lpVtbl;
    };

对这些各个宏定义,真想吐槽

基本上IPersist 内就包含了一个关于IPersistVtbl的指针,这个指针指向了IPersistVtbl的内存地址。 而IPersistVtbl这个结构体中保存了一堆函数指针。如下:

在这里插入图片描述

其中函数指针中的this,代表的就是这个p。

知道这些就可以明白了在C 那个时代COM是怎么实现继承多个接口的。其实就是在虚函数表上挂上多个指针就好了嘛。如下:

在这里插入图片描述

这么一说是不是很像C++里的多重集成?我个人认为这基本上就是C++内多重继承的实现了(大体上),只不过这些this 在写相关类内函数的时候不用自己来写,而是编译器会在编译时候给带上。

结束

正文中基本上是对
The layout of a COM object
中内容的个人理解,如果有哪些不对的欢迎纠正~~🙂

这篇到这里也就该结束了,不得不说The Old New Thing真是个好东西, 能让人了解到不少Windows的历史😃。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值