IDispatchEx Interface
得从IDispatchEx接口开始说起,它是IDispatch的扩展接口。
IDispatch最早是给VB用的,它假设标物(object)是静态的,也就是标物在运行时是不会改变的,编译时所获取的类型信息就是不变的。但是这个假设在脚本语言VBScript以及JScript之上不太合理,于是乎IDispatchEx应用而生。
Ex版实现了IDispatch的全部服务,并提供了一些扩展:
- GetDispID 搭配fdexNameEnsure 可以给标物添加新成员
- DeleteMemberByName 删除成员
- fdexNameCaseSensitive 或fdexNameCaseInsensitive可做大小写区分的联调(dispatch)
- fdexNameImplicit,隐式查找
- InvokeEx
- GetNameSpaceParent支持命名空间
- 成员及其参数的DISPIDs 必须恒定不变
- DISPID 不可以在不同名字的成员间复用
- DISPID 必须对GetNextDispID有效
- DISPID 必须被IDispatch和IDispatchEx 良好接受
Wikipedia IDispatch
对IDispatch的介绍还是比较简单的,主要是下面这句话
IDispatch is the interface that exposes the OLE Automation protocol.
Win32 Automation Creating the IDispatch Interface
IDispatch上的方法们
- GetTypeInfoCount,对于支持IDispatch的标物,此处必须返回1
- GetTypeInfo, 获取接口的TypeInfo
- count只能返回1,是不是意味着此处只能返回一个接口的信息
- 多于一个接口的话需要通过继承来搞定
- 可能是因为VB不支持多继承?
- GetIDsOfNames
- 完成名字到ID的映射
- Invoke
- 呼调标物的方法
实现IDispatch的几种方式
- 通过 DispInvoke、 DispGetIDsOfNames或者通过ITypeInfo::Invoke、 ITypeInfo::GetIDsOfNames来实现,反正都需要TypeInfo
- 调用CreateStdDispatch 直接创建一个接口
- 自行实现,但是Ivoke实现起来还是相当麻烦的
Win32 Automation IDispatch interface (oaidl.h)
比较复杂的是其中的IDispatch::Invoke方法。
Win32 Automation Type Description Interfaces
TypeInfo将虚函数表以元数据的方式体现出来了。
Win32 Automation ITypeLib interface (oaidl.h)
用于查看标类料库(type library)信息。
可能最重要的是ITypeLib::GetTypeInfoOfGuid。
Win32 Automation ITypeInfo interface (oaidl.h)
比较重要的是ITypeInfo::Invoke method (oaidl.h)吧。
C++/WinRT Author COM components with C++/WinRT
Windows Runtime刻意不支持接口派生,具体原因不详。
小结
几点感觉
- Windows这么多年只是在COM的元数据格式上做出了改进,从以前的typelibrary变为现在的windows metadata。
- OLE Automation其实是根据类型来各种互知互联的。
其他
- Implementing the IDispatch Interface
- How do you find a COM’s interfaces without typelib?
- Anatomy of an IDL File
- The dual attribute on IFace3 creates an interface that is both a dispatch interface and a COM interface. Because it is derived from IDispatch, a dual interface supports Automation, which is what the oleautomation attribute specifies. IFace3 imports Oaidl.idl to get the definition of IDispatch.
- dual
- When the dual C++ attribute precedes an interface, it causes the interface to be placed inside the library block in the generated .idl file.
- Generating Interface UUIDs
- 通过命令行uuidgen,可以生成形如
ba209999-0c6c-11d2-97cf-00c04f8eea45
的uuid
- 通过命令行uuidgen,可以生成形如
- Implement COM IDispatch without ATL
- IDispatch的一个实现的例子
- A lightweight approach for exposing C++ objects to a hosted Active Scripting engine
主题链接
- Docs
- WebView2
- 根据Support IDispatchEx for host objects #1195 ,WebView2目前不支持IDispatchEx
- Books
- Columns
- Tools
- WRL
- Authoring and Consuming Classic COM Components with WRL
- WRL doesn’t support generating IDispatch
- Authoring and Consuming Classic COM Components with WRL
- ATL
- C++
- SO
- https://stackoverflow.com/questions/64523333/how-to-implement-idispatch-in-c-com-with-multiple-interfaces
- 这个例子告诉我们,虽然继承了多个接口,只有那个默认的接口管用。
- https://stackoverflow.com/questions/3613491/c-com-design-composition-vs-multiple-inheritance
- https://stackoverflow.com/questions/5478669/good-techniques-for-keeping-com-classes-that-implement-multiple-interfaces-manag
- https://stackoverflow.com/questions/3034285/how-does-implementing-multiple-com-interfaces-work-in-c
- https://stackoverflow.com/questions/64523333/how-to-implement-idispatch-in-c-com-with-multiple-interfaces
(完)