参考&&引用
起因
看来人总是健忘的,只能隐约的记得是因为一个关于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的历史😃。