COM: multiple dual interfaces, again

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance

From: Ville Laakso (use.the_at_sig.luke.invalid)
Date: 06/16/04


Date: 16 Jun 2004 19:06:25 +0300

The issue: implementing multiple dual interfaces with just one class
in a way that enables both vtable-based and scripting clients to have
access to both interfaces' methods.

This topic seems to have shown up here a couple of times earlier with
the general response having been "it's not possible but here are a few
workarounds". As to _why_ it's impossible/illegal, the details have
generally been scarce (or not applicable to what's attempted below).

So, I would like to know what kind of problems the below approach
could present. It _seems_ to work just fine (with C++ and non-makepy
Python). The general idea is to implement IDispatch by trying both of
the IDispatchImpl's on each Invoke() and GetIDsOfNames(). The obvious
problem of overlapping DISPID's is dealt with by manually assigning
different DISPID's for the methods. I guess this requirement could be
lifted by doing slightly more work in GetIDsOfNames() (name conflicts
are trickier to resolve in GION() but let's just assume that they are
unlikely enough in this case).

Comments on the (non-)implementations of the TypeInfo methods are also
appreciated. Don Box's "Essential COM" says that they are "technically
optional" (p. 354). Despite much googling around and browsing MSDN, I
didn't really get a good picture of just how optional they actually
are.

I hope I haven't left anything essential out in my pseudocode-ish
presentation:

// IDL

[ dual, ..., ]
interface A : Dispatch
{
  [id(1)] HRESULT a(void);
}

[ dual, ..., ]
interface B : Dispatch
{
  [id(2)] HRESULT b(void);
}

// C++

class CAB :
 public IDispatchImpl<A,..>
 public IDispatchImpl<B,..>
 public CComObjectRoot,
 public CComCoClass<..>
{

  BEGIN_COM_MAP(CAB)
    COM_INTERFACE_ENTRY(A)
    COM_INTERFACE_ENTRY(B)
    COM_INTERFACE_ENTRY2(IDispatch,A) // kind of counter-intuitive but
                                      // irrelevant (right?)
  END_COM_MAP()

  HRESULT a();
  HRESULT b();

  HRESULT Invoke(DISPID d, ..) {
    if (IDispImp<A>::Invoke(d, ..) == "not found")
      IDispImp<B>::Invoke(d, ..);
  }

  // GetIDsOfNames ~identical to Invoke

  HRESULT GetTypeInfoCount(ulong *result) {
    *result = 0;
  }

  HRESULT GetTypeInfo(..) {
    return E_NOTIMPL;
  }

};

-- 
-Ville Laakso
 firstname <dot> lastname <at> tut <dot> fi


Relevant Pages

  • Re: Mime filter
    ... HRESULT is effectively the same as VOID. ... details of COM from the developer." ... are expect to support an IDispatch or Dual interfaces respect that. ... Everything above is done for the developer by the VBVM ...
    (microsoft.public.vb.general.discussion)
  • Re: Accessing COM Component arguments defined by "ref", after it raise COM+ error
    ... > 32-bit integers in managed code with the MarshalAs attribute applied. ... > Any success HRESULT values are swallowed by the RCW and the values are ... > unattainable from .NET clients unless the managed signature coresponding ... > This all turns out to be a pain so you you shouldn't write interfaces like ...
    (microsoft.public.dotnet.general)
  • RE: How To
    ... A typical use of an enumerator is the following. ... HRESULT IEnum::Next ... Attempt to skip over the next celt elements in the enumeration sequence. ... An object with IDataObject and IPersistFile Interfaces. ...
    (microsoft.public.win32.programmer.ole)
  • Re: WMSDK9 - Concurrent Video/Audio feeds causing one to lose video...
    ... CoCreateInstancereferences the same CLSID and IID_I interfaces ... and succeeds. ... Here is the code that gives me the failing HRESULT when using ...
    (microsoft.public.windowsmedia.sdk)
  • Re: object system...
    ... MI); there are Interfaces, ... modifiable operators like this don't exist in most languages, ... about a sane multiple dispatch instead of the mess. ... probably be optimized via a hash table or similar...). ...
    (comp.object)