Interfaccia IMarshal (objidlbase.h)

Consente a un oggetto COM di definire e gestire il marshalling dei puntatori a interfaccia.

Ereditarietà

L'interfaccia IMarshal eredita dall'interfaccia IUnknown . IMarshal include anche questi tipi di membri:

Metodi

L'interfaccia IMarshal include questi metodi.

 
IMarshal::D isconnectObject

Il metodo IMarshal::D isconnectObject (objidlbase.h) rilascia tutte le connessioni a un oggetto il cui server chiama l'implementazione dell'oggetto di questo metodo.
IMarshal::MarshalInterface

Il metodo IMarshal::MarshalInterface (objidlbase.h) esegue il marshalling di un puntatore dell'interfaccia.
IMarshal::ReleaseMarshalData

Il metodo IMarshal::ReleaseMarshalData (objidlbase.h) elimina un pacchetto di dati con marshalling.
IMarshal::UnmarshalInterface

Il metodo IMarshal::UnmarshalInterface (objidlbase.h) annulla un puntatore dell'interfaccia.

Commenti

Il marshalling è il processo di creazione di pacchetti di dati in pacchetti per la trasmissione a un processo o un computer diverso. Unmarshaling è il processo di recupero dei dati alla fine della ricezione. In qualsiasi chiamata specificata, gli argomenti del metodo vengono marshallati e non collegati in una direzione, mentre i valori restituiti vengono marshallati e non si separano dall'altro.

Anche se il marshalling si applica a tutti i tipi di dati, i puntatori di interfaccia richiedono una gestione speciale. Il problema fondamentale è il modo in cui il codice client in esecuzione in uno spazio indirizzi può dereferenziare correttamente un puntatore a un'interfaccia in un oggetto che risiede in uno spazio indirizzi diverso. La soluzione COM è destinata a un'applicazione client per comunicare con l'oggetto originale tramite un oggetto surrogato o un proxy, che vive nel processo del client. Il proxy contiene un riferimento a un'interfaccia sull'oggetto originale e passa il client a un puntatore a un'interfaccia stessa. Quando il client chiama un metodo di interfaccia nell'oggetto originale, la chiamata verrà effettivamente eseguita nel proxy. Pertanto, dal punto di vista del client, tutte le chiamate sono in-process.

Durante la ricezione di una chiamata, il proxy esegue il marshalling degli argomenti del metodo e tramite alcuni mezzi di comunicazione tra processi, ad esempio RPC, li passa al codice nel processo del server, che annulla gli argomenti e li passa all'oggetto originale. Lo stesso marshalling del codice restituisce i valori per la trasmissione al proxy, che annulla i valori e li passa all'applicazione client.

IMarshal fornisce metodi per la creazione, l'inizializzazione e la gestione di un proxy in un processo client; non determina come il proxy deve comunicare con l'oggetto originale. L'implementazione predefinita COM di IMarshal usa RPC. Quando si implementa questa interfaccia, è possibile scegliere qualsiasi metodo di comunicazione interprocesso che si ritiene appropriato per l'applicazione, memoria condivisa, pipe denominata, handle di finestra, RPC, in breve, qualsiasi cosa funziona.

Implementazione predefinita di IMarshal

COM usa la propria implementazione interna dell'interfaccia IMarshal per eseguire il marshalling di qualsiasi oggetto che non fornisce la propria implementazione. COM rende questa determinazione eseguendo una query sull'oggetto per IMarshal. Se l'interfaccia è mancante, COM è predefinita per l'implementazione interna.

L'implementazione predefinita COM di IMarshal usa un proxy generico per ogni oggetto e crea singoli stub e proxy, in base alle esigenze, per ogni interfaccia implementata nell'oggetto. Questo meccanismo è necessario perché COM non può conoscere in anticipo quali interfacce specifiche possono implementare un determinato oggetto. Gli sviluppatori che non usano il marshalling predefinito COM, scegliere invece di scrivere le proprie routine proxy e marshalling, sapere in fase di compilazione tutte le interfacce da trovare negli oggetti e quindi comprendere esattamente quale codice di marshalling è necessario. COM, fornendo supporto di marshalling per tutti gli oggetti, deve farlo in fase di esecuzione.

Il proxy di interfaccia risiede nel processo client; lo stub dell'interfaccia risiede nel server. Insieme, ogni coppia gestisce tutti i marshalling per l'interfaccia. Il processo di ogni proxy di interfaccia consiste nel marshalling di argomenti e nei parametri restituiti e nonmarshal passati indietro e indietro nelle chiamate successive alla relativa interfaccia. Il processo di ogni stub dell'interfaccia consiste nell'annullare gli argomenti delle funzioni e passarli all'oggetto originale e quindi eseguire il marshalling dei valori restituiti e dei parametri restituiti dall'oggetto.

Proxy e stub comunicano tramite un canale RPC (chiamata di routine remota) che usa l'infrastruttura RPC del sistema per la comunicazione tra processi. Il canale RPC implementa un'unica interfaccia, IRpcChannelBuffer, a cui entrambi i proxy di interfaccia e gli stub contengono un puntatore. Il proxy e lo stub chiamano l'interfaccia per ottenere un pacchetto di marshalling, inviare i dati alla controparte e distruggere il pacchetto al termine. Lo stub dell'interfaccia contiene anche un puntatore all'oggetto originale.

Per qualsiasi interfaccia specificata, il proxy e lo stub vengono entrambi implementati come istanze della stessa classe, elencate per ogni interfaccia nel Registro di sistema nell'etichetta ProxyStubClsid32. Questa voce esegue il mapping dell'IID dell'interfaccia al CLSID degli oggetti proxy e stub. Quando COM deve eseguire il marshalling di un'interfaccia, viene visualizzata nel Registro di sistema per ottenere il CLSID appropriato. Il server identificato da questo CLSID implementa sia il proxy dell'interfaccia che lo stub dell'interfaccia.

La classe a cui fa riferimento CLSID viene generata automaticamente da uno strumento il cui input è una descrizione delle firme delle funzioni e della semantica di un'interfaccia specificata, scritta in un linguaggio di descrizione dell'interfaccia. Anche se l'uso di tale lingua è altamente consigliato e incoraggiato per l'accuratezza, non è necessario farlo. I proxy e gli stub sono semplicemente componenti COM usati dall'infrastruttura RPC e, di conseguenza, possono essere scritti in qualsiasi modo desiderato, purché vengano mantenuti i contratti esterni corretti. Il programmatore che progetta una nuova interfaccia è responsabile della garanzia che tutti i proxy di interfaccia e gli stub che esistano sempre sono d'accordo sulla rappresentazione dei dati in marshalling.

Quando creato, i proxy di interfaccia vengono sempre aggregati in un proxy di dimensioni maggiori, che rappresenta l'oggetto nel suo complesso. Questo proxy oggetto aggrega anche l'oggetto proxy generico COM, noto come gestione proxy. Il gestore proxy implementa due interfacce: IUnknown e IMarshal. Tutte le altre interfacce che possono essere implementate in un oggetto vengono esposte nel proxy oggetto tramite l'aggregazione di singoli proxy di interfaccia. Un client che contiene un puntatore al proxy dell'oggetto "crede" contiene un puntatore all'oggetto effettivo.

Un proxy che rappresenta l'oggetto nel suo complesso è necessario nel processo client in modo che un client possa distinguere le chiamate alle stesse interfacce implementate in oggetti completamente diversi. Tale requisito non esiste nel processo server, tuttavia, in cui risiede l'oggetto stesso, perché tutti gli stub di interfaccia comunicano solo con gli oggetti per cui sono stati creati. Nessun'altra connessione è possibile.

Gli stub dell'interfaccia, a differenza dei proxy di interfaccia, non vengono aggregati perché non è necessario che vengano visualizzati in un client esterno che faccia parte di un intero intero. Quando è connesso, viene assegnato un puntatore all'oggetto server a cui deve inoltrare le chiamate al metodo che riceve. Anche se è utile fare riferimento concettuale a un gestore stub, ovvero qualsiasi parte di codice e stato nell'infrastruttura RPC lato server che servizi la comunicazione remota di un determinato oggetto, non esiste alcun requisito diretto che il codice e lo stato accettano qualsiasi modulo specifico, ben specificato.

La prima volta che un client richiede un puntatore a un'interfaccia in un oggetto specifico, COM carica uno stub IClassFactory nel processo del server e lo usa per eseguire il marshalling del primo puntatore al client. Nel processo client COM carica il proxy generico per l'oggetto class factory e chiama l'implementazione di IMarshal per annullare il puntatore. COM crea quindi il primo proxy di interfaccia e lo passa al canale RPC. Infine, COM restituisce il puntatore IClassFactory al client, che lo usa per chiamare IClassFactory::CreateInstance, passandolo un riferimento all'interfaccia.

Nel processo del server, COM crea ora una nuova istanza dell'oggetto, insieme a uno stub per l'interfaccia richiesta. Questo stub esegue il marshalling del puntatore dell'interfaccia al processo client, in cui viene creato un altro proxy oggetto, questa volta per l'oggetto stesso. Viene anche creato un proxy per l'interfaccia richiesta, un puntatore a cui viene restituito al client. Con le chiamate successive ad altre interfacce nell'oggetto, COM caricherà gli stub e i proxy dell'interfaccia appropriati in base alle esigenze.

Quando viene creato un nuovo proxy di interfaccia, COM lo applica un puntatore all'implementazione di IUnknown di Gestione proxy, a cui delega tutte le chiamate QueryInterface . Ogni proxy di interfaccia implementa due interfacce personalizzate: l'interfaccia che rappresenta e IRpcProxyBuffer. Il proxy di interfaccia espone direttamente la propria interfaccia ai client, che possono ottenere il puntatore chiamando QueryInterface nella gestione proxy. Solo COM, tuttavia, può chiamare IRpcProxyBuffer, che viene usato per connettersi e disconnettere il proxy al canale RPC. Un client non può eseguire query su un proxy di interfaccia per ottenere un puntatore all'interfaccia IRpcProxyBuffer .

Sul lato server ogni stub dell'interfaccia implementa IRpcStubBuffer. Il codice del server che funge da gestore stub chiama IRpcStubBuffer::Connect e passa il puntatore IUnknown dell'oggetto.

Quando un proxy di interfaccia riceve una chiamata al metodo, ottiene un pacchetto di marshalling dal suo canale RPC tramite una chiamata a IRpcChannelBuffer::GetBuffer. Il processo di marshalling degli argomenti copia i dati nel buffer. Al termine del marshalling, il proxy dell'interfaccia richiama IRpcChannelBuffer::SendReceive per inviare il pacchetto marshalling al stub dell'interfaccia corrispondente. Quando IRpcChannelBuffer::SendReceive restituisce, il buffer in cui gli argomenti sono stati sottoposti a marshalling sarà stato sostituito da un nuovo buffer contenente i valori restituiti sottoposti a marshalling dallo stub dell'interfaccia. Il proxy dell'interfaccia annulla i valori restituiti, richiama IRpcChannelBuffer::FreeBuffer per liberare il buffer e quindi restituisce i valori restituiti al chiamante originale del metodo.

È l'implementazione di IRpcChannelBuffer::SendReceive che invia effettivamente la richiesta al processo del server e che sa come identificare il processo del server e, all'interno di tale processo, l'oggetto a cui inviare la richiesta. L'implementazione del canale sa anche come inoltrare la richiesta al gestore stub appropriato in tale processo. Lo stub dell'interfaccia annulla ilmarshal degli argomenti dal buffer fornito, richiama il metodo indicato nell'oggetto server e esegue il marshalling dei valori restituiti in un nuovo buffer allocato da una chiamata a IRpcChannelBuffer::GetBuffer. Il canale trasmette quindi il pacchetto di dati restituito al proxy di interfaccia, che è ancora al centro di IRpcChannelBuffer::SendReceive, che restituisce al proxy di interfaccia.

Un'istanza specifica di un proxy di interfaccia può essere usata per il servizio più di un'interfaccia, purché vengano soddisfatte le condizioni seguenti:

  • Gli ID delle interfacce interessate devono essere mappati al ProxyStubClsid appropriato nel Registro di sistema.
  • Il proxy di interfaccia deve supportare chiamate a QueryInterface da un'interfaccia supportata alle altre interfacce, come di consueto, nonché da IUnknown e IRpcProxyBuffer.
Una singola istanza di uno stub dell'interfaccia può anche essere gestita più di un'interfaccia, ma solo se tale set di interfacce ha una relazione di ereditarietà singola rigorosa. Questa restrizione esiste perché lo stub può indirizzare le chiamate al metodo a più interfacce solo dove sa in anticipo quali metodi vengono implementati in anticipo su quali interfacce.

In vari momenti, i proxy e gli stub dovranno allocare o liberare memoria. I proxy di interfaccia, ad esempio, dovranno allocare memoria in cui restituire i parametri al chiamante. In questo senso, i proxy di interfaccia e gli stub dell'interfaccia sono solo componenti COM normali, in quanto devono usare l'allocatore di attività standard. Vedere CoGetMalloc.

Requisiti

Requisito Valore
Client minimo supportato Windows 2000 Professional [app desktop | App UWP]
Server minimo supportato Windows 2000 Server [app desktop | App UWP]
Piattaforma di destinazione Windows
Intestazione objidlbase.h (include ObjIdl.h)

Vedi anche

IStdMarshalInfo