A dual interface is an interface that combines a dispatch interface and a direct vtable interface. One advantage of dual interfaces is that they let the caller choose the binding mechanism it wants to use. Scripting languages can use the dispatch interface while C++ callers can use the direct vtable interface. This means that objects that export dual interfaces are more useful since they can be used by a wider range of callers. IDispatch offers support for late binding, whereas vtable binding offers much higher performance because the method is called directly instead of going through IDispatch::Invoke. IDL supports the definition of dual interfaces. This is done by deriving the interface from IDispatch and attaching the [dual] attribute to the interface statement (notice that the dispinterface statement is not used). Here is the IDL declaration of IStack suitable for a dual interface. [ uuid(FC3B3F51-BCED-11D1-91FE-E1CBED988F66) ] library StackLib { importlib("stdole32.tlb"); [ object, dual, uuid(FC3B3F51-BCEC-11D1-91FE-E1CBED988F66) ] interface IStack : IDispatch { [id(1)] HRESULT push([in] long value); [id(2)] HRESULT pop([out, retval] long* value); [id(3)] HRESULT empty([out, retval] long* pVal); }; }; Since dual interfaces are COM interfaces, they must abide by the rules for COM interfaces.
Since dual interfaces are dispatch interfaces, they must abide by the rules for dispatch interfaces.
A dual interface inherits from IDispatch and also implicitly inherits from IUnknown (since IDispatch inherits from IUnknown). At a binary level, the first three entries in the vtable are the members of IUnknown, the next four entries are the members of IDispatch, and the subsequent entries are pointers to the custom methods of the dual interface. Thus Automation controllers can access the IDispatch interface (including GetIDsOfNames and Invoke) since the entries for the dispatch interface are at the same locations in the vtable whether or not this is a dual interface. Other callers who are aware of dual interfaces can bind directly to the custom methods in the COM interface. Information about the physical layout of the vtable is obtained from a type library or a header file. Direct vtable binding can be two to five times faster than Automation binding for in-process calls. |