COM interface types. A quick glossary
Categories
Right. Let's brush away some cobwebs, and write this down so I don't have to google all over the web whenever I need a quick COM 101 refresher:
- A custom or vtable interface is a COM interface that derives from IUnkown. It only supports early binding through the compiler's vtable.
- A dispinterface is a purely IDispatch based interface. The methods defined in the IDL file are only callable via IDispatch::Invoke, and not via a vtable. These are usually used as event interfaces (i.e. you implement the interface on your object and pass it to another object that you want to receive events from). Knowing this explains why it's not a cardinal COM sin that Microsoft have been expanding DWebBrowserEvents2 for each release of Internet Explorer.
- A dual interface is a COM interface that derives from both IUnknown and IDispatch - it's both a vtable interface and a dispinterface.
- Expando objects implement IDispatchEx and allow you to add methods and properties at runtime. This is how JavaScript, VBScript and Internet Explorer allow you to expand script and HTML objects.
A type library can be used to store interface information. It can contain vtable layouts and the DispId's required to call IDispatch based interfaces.
You can implement IDispatch by hand, with a huge switch statement, if you want to, but remember that you'll need to crack the parameters out of arrays and stuff them back in again for the return value.
Alternatively, you can let someone else do the heavy lifting for you and use an implementation of IDispatch which is based on a type library. (And seeing how one of the methods of IDispatch is to get a pointer to an ITypeInfo interface representing a type library - you might as well). This works by calling LoadTypeLib to get an instance of ITypeLib, then calling ITypeLib::GetTypeInfoOfGuid. The resulting ITypeInfo can be used to defer the interesting IDispatch methods (including Invoke). This is what ATL's IDispatchImpl does. It's interesting to note that the Invoke method will call vtable based methods on your interface. This is pretty good voodoo.
As far as I can make out, you could also use CreateStdDispatch to create an IDispatch interface for you, which essentially does the same thing as IDispatchImpl. Or, you can implement bits of IDispatch yourself and defer to methods such as DispInvoke and DispGetIDsOfNames.
If you want to support dispinterfaces, you can use ATL's IDispEventImpl. This is an implementation of IDispatch that doesn't require an implementation of each member on the dispinterface. It does this by using a map that routes DispId's to functions - ideal for an interface that doesn't actually have a vtable. You could even use IDispEventSimpleImpl if you didn't want to use a typelib.
Sheesh. It's nice that .net moves well away from all of this malarky, but it's still something that you need to know from time to time...