2009-11-12 8 views
6

Come ho capito ci sei tre modi per implementare smistamento in COM:In che modo COM seleziona come eseguire il marshalling di un'interfaccia?

  • libreria dei tipi di smistamento
  • proxy/stub smistamento
  • attuazione IMarshal dall'oggetto

ora come funziona il componente consumatore (utente) scegliere quale sarà utilizzato? Decide da solo e usa il modo preferito o chiama alcune funzioni built-in e risolve il problema?

Attualmente ho riscontrato quanto segue: il mio componente implementa un'interfaccia personalizzata ICustomInterface implementata anche da un componente di un'altra azienda. Il mio componente non ha una libreria dei tipi e non implementa IMarshal. Il registro di sistema contiene la chiave HKCR \ Interface {uuidof (ICustomInterface)} \ ProxyStubClsid32 con un GUID del proxy/stub che può essere rintracciato in una libreria fornita da quell'altra società.

Ora, quando il mio componente consumer inizializza il componente, chiama QueryInterface() che richiede IMarshal dal mio componente e quando viene restituito E_NOINTERFACE non fa nulla. Perché questo è il motivo per cui kicker la libreria proxy/stub dall'altra azienda?

risposta

0

Sono un po 'arrugginito in questo, ma nel tuo progetto hai una funzione chiamata blindquery? (Solitamente viene dichiarato dalla procedura guidata se è stato creato un progetto ATL C++). Breakpoint all'interno della funzione. La funzione è generata dalla procedura guidata spesso ha problemi con queryinterface restituendo E_NOINTERFACE a causa di codice buggato.

modifica (codice di esempio trovato) dal mio vecchio progetto _ blindquery

class ATL_NO_VTABLE CChildEvents : 
    public CComObjectRootEx <CComSingleThreadModel>, 
    public CComCoClass<CChildEvents, &CLSID_ChildEvents>, 
    public IDispatchImpl<IChildEvents, &IID_IChildEvents, &LIBID_XXX> 
{ 
public: 
    CChildEvents(void) : 
    m_pItfMgr(0) 
    { 
    } 

    /* called from internalQI to tear off a new blind interface */ 
    static HRESULT WINAPI _BlindQuery(void *pvThis, REFIID riid, void **ppv, DWORD dw); 

    DECLARE_REGISTRY_RESOURCEID(IDR_CHILDEVENTS) 
    DECLARE_PROTECT_FINAL_CONSTRUCT() 

    BEGIN_COM_MAP(CChildEvents) 
     COM_INTERFACE_ENTRY(IChildEvents) 
     COM_INTERFACE_ENTRY(IDispatch) 
     COM_INTERFACE_ENTRY_FUNC_BLIND(0, _BlindQuery) 
    END_COM_MAP() 
}; 


HRESULT WINAPI CChildEvents::_BlindQuery(void *pvThis, REFIID riid, void **ppv, DWORD /* dw */) 
{ 
    HRESULT hr = E_NOINTERFACE; 
    USES_CONVERSION; 

    try 
    { 
     if(pvThis == NULL) 
     { 
      ATLASSERT(FALSE); 
     } 
     else 
     { 
      /* 
      * cast the pvThis pointer to the actual class £ 
      * so we can use it here £ 
      * reinterpret_cast should be safe since we're calling ourself 
      */ 
      CChildEvents *pThis = reinterpret_cast < CChildEvents * > (pvThis); 
      if(pThis == NULL) 
      { 
       ATLASSERT(FALSE); 
      } 
      else 
      { 

        /* check to see if it matches on of our children's DIID */ 
            if(memcmp(&riid,&l_someotherguid,sizeof(GUID)) == 0) { 

         /* if so cast to a IDispatch -- the standard for event interfaces */ 
         *ppv = reinterpret_cast < IDispatch * > (pvThis); 

         /* addref */ 
         pThis->AddRef(); 

         /* reply */ 
         hr = S_OK; 

       } 
      } 
     } 
    } 
    catch(...) 
    { 
     ATLASSERT(FALSE); 
    } 

    /* must not be in our map - tell them to GO FISH */ 
    return(hr); 
} 
+0

No, non ne ho uno. Ho provato il wizard con tutte le impostazioni ragionevoli e non dichiara tale funzione. Ho anche cercato su Google questo nome - nessuna corrispondenza ragionevole. Potrebbe essere che hai scritto male il nome? – sharptooth

+0

ho scavato nel mio vecchio codice e ho scoperto che la query cieca era in realtà la mia funzione. LOL .. usa questa macro http://msdn.microsoft.com/en-us/library/5b6w5bwx(VS.80).aspx –

+0

Bene, questo è un bel modo di aggancio al QI().Ma questo è tutto - la funzione è chiamata per un insieme di iterfaces, incluso IMarshal, senza apparenti motivi. – sharptooth

5

Il runtime COM utilizzerà libreria dei tipi (oleautomation) di smistamento Se si contrassegna l'interfaccia come utilizzando il marshalling standard aggiungendo il suo CLSID {00020424-0000-0000-C000-000000000046} sotto HKCR\Interfaces\{iid}\ProxyStubClsid (dove {iid} è il GUID della tua interfaccia). È necessario registrare anche una libreria dei tipi, affinché il runtime estragga le informazioni sui parametri e si può utilizzare solo un determinato sottoinsieme di tipi. Ci sono altre (vecchie) informazioni here e here.

Se si desidera utilizzare un proxy/stub personalizzato, come generato dal compilatore MIDL dal proprio IDL, sarà necessario modificare la voce del registro di interfaccia in modo che sia il CLSID di tale oggetto proxy. Ciò ti consente di utilizzare una gamma più ampia di tipi, ad es. array "grezzi".

Se si supporta IMarshal, questo è ciò che verrà utilizzato preferibilmente a uno di questi meccanismi. Ciò significa che è possibile modificare l'oggetto per aggregare il gestore di marshalling a thread libero (utilizzando la sua implementazione di IMarshal) senza dover modificare nulla nel registro. Ciò eviterà la creazione di proxy.

Spero che questo aiuti.

+0

Ma perché vedo uno strano comportamento - in particolare il runtime prima QI il mio componente per IMarshal e quando ottiene E_NOINTERFACE viene semplicemente richiamato, non cercando di cercare la chiave HKCR \ Interface \ {InterfaceId}? – sharptooth

+0

Hai visto i documenti qui http://msdn.microsoft.com/en-us/library/ms678428%28VS.85%29.aspx? Forse potresti mettere insieme un piccolo test case che chiama CoMarshalInterface (che è in definitiva ciò che farà il runtime COM), e tracciare per vedere cosa succede. L'ho provato e con il rammarico ho potuto vederlo colpire il registro. – voyce

Problemi correlati