4.1 COM接口类型概述
描述:除了Vtable结构的接口外,COM还支持另外两种接口类型:即派发接口(Dispinterface)和双向接口(Dual Interface)
4.1.1 Vtable 接口
1)Vtable类型接口的缺点是需要在编译时与客户机程序进行某种形式的绑定,也就是客户机必须清楚编译阶段的接口方法和接口参数.由于这些静态信息并不包含组件中方法的具体实现,所以COM的多态性刚好解决了这一问题.
2)一个接口的函数特征是在编译阶段被定义的,而不是在接口方法的实际实现时被定义的
4.1.2 IDispatch 接口:Dispinterface
1)与Vtable不同,它可以在运行时决定方法的名字和参数,但速度慢.
4.1.3 双向接口
1)一个双向接口(dual-interface)就是一个普通的COM Vtable接口和一个Dispinerface接口的结合
4.2 组件及其接口的描述
描述:为了使客户访问组件的接口,必须对接口进行描述
1)描述Vtable接口的布局,每一个方法参数的类型以及参数的数量
2)对接口的描述可用于产生基于特定语言的绑定信息
3)提供支持调度功能,使客户能够跨进程和跨计算机访问组件
4.2.1 类型信息
1)组件使用IDL对它们的接口进行描述.用MIDL.EXE可将它们编译到类型库中.
2)组件使用一个二进制的,独立于语言的文件对它本身的功能进行描述,也就是type library(类型库)
4.2.1.1 语言绑定
IDL所描述的组件,也可以产生特定语言的文件.MIDL编译器只为C/C++语言产生绑定信息,其他语言则使用类型库来产生编译时绑定.
4.2.1.2 生成PROXY/STUB
MIDL编译IDL文件可得到proxy/stub DLL代码以及make文件.proxy/stub DLL为每一个接口实现标准调度
4.2.2 调度
1)概念:调度是指在进程和计算机之间进行函数参数和返回值传输的一个过程.
2)在多线程应用程序中,COM使用调度来同步对组件的访问,因而即使你的组件只支持在进程内执行,有时也需要提供调度支持.
3)COM在实现调度时使用一个proxy和一个stub.调度时,客户进程空间创建proxy对象,组件进程空间创建一个stub对象.
4)下列情况需要调度
a.访问一台计算机不同进程中的组件时
b.访问不同计算机上的组件时(DCOM).
c.同一个进程组件的不同部分之间传输接口指针时.
4.3 分布式COM
1)概念:分布式COM是指COM可以将它的组件分布在网络中,并能够在不同的计算机上对它进行访问
4.4 标准调度
1)MIDL编译器编译IDL将产生一些文件用于构造proxy/stub DLL.
2)为了能够创建并注册proxy/stub DLL,必须为你的组件提供标准调度
3)proxy/stub必须在每一台客户机上注册
MIDL 编译产生的proxy/stub文件
文件 说明
ProjectNamePS.mk 该make文件生成名为ProjectNamePS.dll的proxy/stub动态链接库
ProjectName.h 与C 和 C++ 兼容的接口声明头文件
ProjectName_p.c 包含实现proxy/stub代码的源文件
ProjectName_i.c 包含接口GUID的C源文件
DLLDATA.C 为proxy/stub代码实现DLL的C源文件
4.4.1 类型库(通用)调度
1)类型库使用标准的自动化调度器实现调度,前提是你的接口方法中只能使用与自动化(Automation)兼容的类型
2)为了使用类型库调度,应确保组件中只使用自动化类型,并在IDL文件的接口声明中添加oleautomation属性
// 由于IMath接口只使用与自动化兼容的类型,因此你可以使用类型库调度
[
object,
uuid(8C30BC10-88F2-11D0-A756-B04A12000000),
oleautomation,
helpstring("IMath Interface"),
pointer_default(unique)
]
interface IMath : IUnknown
{
HRESULT Add([in]long,[in]long,[out,retval]long *);
HRESULT Subtract([in] long, [in] long, [out,retval]long *);
HRESULT Multiply([in] long, [in] long, [out,retval]long *);
HRESULT Divide([in] long, [in] long, [out,retval] long *);
};
3)实现类型库调度所需的另一个步骤是,使用COM提供的RegisterTyp