Interfaccia IMarshal (objidl.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 ha anche questi tipi di membri:

Metodi

L'interfaccia IMarshal ha questi metodi.

 
IMarshal::D isconnectObject

Il metodo IMarshal::D isconnectObject (objidl.h) rilascia tutte le connessioni a un oggetto prima dell'arresto.
IMarshal::GetMarshalSizeMax

Recupera le dimensioni massime del buffer che saranno necessarie durante il marshalling.
IMarshal::GetUnmarshalClass

Recupera il CLSID del codice di annullamento delmarshaling.
IMarshal::MarshalInterface

Il metodo IMarshal::MarshalInterface (objidl.h) effettua il marshalling di un puntatore all'interfaccia.
IMarshal::ReleaseMarshalData

Il metodo IMarshal::ReleaseMarshalData (objidl.h) elimina definitivamente un pacchetto di dati sottoposto a marshalling.
IMarshal::UnmarshalInterface

Il metodo IMarshal::UnmarshalInterface (objidl.h) annulla unmarshal un puntatore all'interfaccia.

Commenti

Il marshalling è il processo di creazione di pacchetti di dati in pacchetti per la trasmissione a un altro processo o computer. Unmarshaling è il processo di recupero dei dati alla fine della ricezione. In una determinata chiamata, gli argomenti del metodo vengono sottoposto a marshalling e non si separano in una direzione, mentre i valori restituiti vengono sottoposto a marshalling e non sincronizzati nell'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 su un oggetto che risiede in uno spazio indirizzi diverso. La soluzione COM consente a un'applicazione client di comunicare con l'oggetto originale tramite un oggetto surrogato o un proxy, che risiede nel processo del client. Il proxy contiene un riferimento a un'interfaccia sull'oggetto originale e consegna al client un puntatore a un'interfaccia stessa. Quando il client chiama un metodo di interfaccia sull'oggetto originale, la chiamata viene effettivamente eseguita al proxy. Pertanto, dal punto di vista del client, tutte le chiamate sono in-process.

Quando riceve una chiamata, il proxy effettua il marshalling degli argomenti del metodo e tramite alcuni mezzi di comunicazione interprocesso, ad esempio RPC, li passa al codice nel processo del server, che annulla ilmarso degli argomenti e li passa all'oggetto originale. Lo stesso codice esegue il marshalling dei valori restituiti per la trasmissione al proxy, che annulla ilmarso dei 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 manualmente, è possibile scegliere qualsiasi metodo di comunicazione interprocesso ritenuta appropriata per l'applicazione, ovvero memoria condivisa, named pipe, handle di finestra, RPC, in breve, qualunque cosa funzioni.

Implementazione predefinita di IMarshal

COM usa la propria implementazione interna dell'interfaccia IMarshal per effettuare il marshalling di qualsiasi oggetto che non fornisce la propria implementazione. COM determina questa determinazione eseguendo una query sull'oggetto per IMarshal. Se l'interfaccia non è presente, per impostazione predefinita COM viene eseguita 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ò sapere in anticipo quali interfacce particolari possono implementare un determinato oggetto. Gli sviluppatori che non usano il marshalling predefinito COM, scelgono invece di scrivere le proprie routine proxy e marshalling, sanno in fase di compilazione tutte le interfacce da trovare sui propri oggetti e quindi capiscono esattamente quale codice di marshalling è necessario. COM, fornendo il supporto del 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 tutto il marshalling per l'interfaccia. Il processo di ogni proxy di interfaccia consiste nel effettuare il marshalling di argomenti e di annullare il marshalling dei valori restituiti e dei parametri out passati avanti e indietro nelle chiamate successive alla relativa interfaccia. Il processo di ogni stub di interfaccia consiste nell'annullare gli argomenti della funzione e passarli all'oggetto originale e quindi effettuare il marshalling dei valori restituiti e dei parametri out restituiti dall'oggetto.

Il proxy e lo stub comunicano tramite un canale RPC (remote procedure call), che utilizza l'infrastruttura RPC del sistema per la comunicazione interprocesso. Il canale RPC implementa una singola 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 specifica, il proxy e lo stub vengono entrambi implementati come istanze della stessa classe, elencate per ogni interfaccia nel Registro di sistema sotto l'etichetta ProxyStubClsid32. Questa voce esegue il mapping dell'IID dell'interfaccia al CLSID dei relativi oggetti proxy e stub. Quando COM deve effettuare il marshalling di un'interfaccia, cerca nel Registro di sistema di ottenere il CLSID appropriato. Il server identificato da questo CLSID implementa sia il proxy di interfaccia che lo stub dell'interfaccia.

Nella maggior parte dei casi, la classe a cui fa riferimento questo CLSID viene generata automaticamente da uno strumento il cui input è una descrizione delle firme di funzione e della semantica di una determinata interfaccia, scritta in un linguaggio di descrizione dell'interfaccia. Anche se l'uso di tale linguaggio è altamente consigliato e incoraggiato per l'accuratezza, questa operazione non è necessaria. I proxy e gli stub sono semplicemente componenti COM utilizzati 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 di garantire che tutti i proxy di interfaccia e gli stub esistenti siano d'accordo sulla rappresentazione dei dati di marshalling.

Al momento della creazione, i proxy di interfaccia vengono sempre aggregati in un proxy più grande, 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 su oggetti completamente diversi. Tale requisito non esiste nel processo del 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 di interfaccia, a differenza dei proxy di interfaccia, non vengono aggregati perché non è necessario che sembrino che alcuni client esterni facciano parte di un intero più grande. Quando si è connessi, agli stub di interfaccia viene assegnato un puntatore all'oggetto server a cui inoltrare le chiamate al metodo ricevute. Anche se è utile fare riferimento concettualmente a un gestore stub, ovvero qualsiasi parte di codice e stato nell'infrastruttura RPC lato server che serve la comunicazione remota di un determinato oggetto, non è necessario che il codice e lo stato abbiano un formato specifico e ben specificato.

La prima volta che un client richiede un puntatore a un'interfaccia su un oggetto specifico, COM carica uno stub IClassFactory nel processo server e lo usa per effettuare 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 tale puntatore. COM crea quindi il primo proxy di interfaccia e lo consegna a un puntatore 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 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 creato anche un proxy per l'interfaccia richiesta, un puntatore a cui viene restituito il client. Con le chiamate successive ad altre interfacce sull'oggetto, COM caricherà gli stub e i proxy dell'interfaccia appropriati in base alle esigenze.

Quando viene creato un nuovo proxy di interfaccia, COM passa un puntatore all'implementazione di IUnknown del gestore proxy, a cui delega tutte le chiamate QueryInterface . Ogni proxy di interfaccia implementa due interfacce proprie: 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 lo stub dell'interfaccia il puntatore IUnknown dell'oggetto.

Quando un proxy di interfaccia riceve una chiamata al metodo, ottiene un pacchetto di marshalling dal 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 di interfaccia richiama IRpcChannelBuffer::SendReceive per inviare il pacchetto sottoposto a marshalling allo stub dell'interfaccia corrispondente. Quando IRpcChannelBuffer::SendReceive restituisce, il buffer in cui gli argomenti sono stati sottoposto a marshalling sarà stato sostituito da un nuovo buffer contenente i valori restituiti di cui viene eseguito il marshalling dallo stub dell'interfaccia. Il proxy di 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 ilmarsalamento degli argomenti dal buffer fornito, richiama il metodo indicato nell'oggetto server e effettua 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 torna al proxy di interfaccia.

Una particolare istanza di un proxy di interfaccia può essere usata per gestire più interfacce, 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 le chiamate a QueryInterface da un'interfaccia supportata alle altre interfacce, come di consueto, nonché da IUnknown e IRpcProxyBuffer.
Una singola istanza di uno stub di interfaccia può anche eseguire il servizio di 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 in cui sa in anticipo quali metodi vengono implementati 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 di 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 objidl.h (include ObjIdl.h)

Vedi anche

IStdMarshalInfo