Per prima cosa: stai parlando di COM Interop qui (ITaskTrigger
è un'interfaccia COM), non P/Invoke. Ci sono diverse regole di interoperabilità per i due, quindi è importante mantenerli dritti. Ad esempio, dovrai definire wrapper di interoperabilità C# per l'intera interfaccia, non solo il metodo che desideri. Questi dovrebbero iniziare: pinvoke.net
La risposta breve è, sei fortunato, perché il CLR dovrebbe prendersi cura delle cose correttamente per voi.
La risposta più lunga riguarda i diversi tipi di marshalling del codice di interoperabilità COM, a seconda dei tipi di parametri, delle direzioni e di quali attributi si aggiungono alle proprie firme di interoperabilità.
In questo caso, il tipo di parametro che si otterrà nella chiamata è un parametro "out string
" con un attributo MarshalAs(UnmanagedType.LPWSTR)
. Quando un server COM espone una chiamata con un parametro "out" del tipo di stringa LPWSTR
, supponendo che il server mantenga la sua posizione finale, allocherà un buffer di memoria con CoTaskMemAlloc()
e lo restituirà all'utente. (Se si trattava di un tipo di stringa diverso, ad esempio BSTR
, la chiamata di allocazione di memoria specifica potrebbe essere diversa, ma il concetto di base è lo stesso.) A questo punto, sei responsabile della pulizia di quella memoria quando non ne hai più bisogno, utilizzando la chiamata CoTaskMemFree()
corrispondente.
Questo è un particolare tipo di operazione chiamata un "cambio di riferimento": il parametro che si sta inviando in è già un parametro di riferimento, ma il server COM sta per sostituirlo con un diverso di riferimento . Una buona spiegazione per questo processo si trova nella sezione "Proprietà della memoria" di this MSDN magazine article. Come puoi vedere da questo articolo, quando il CLR riceve i dati da un parametro "out" su un tipo di riferimento, riconosce che si sta assumendo la responsabilità di liberare quella memoria. Durante il marshalling che richiama il codice gestito, utilizza l'attributo MarshalAs
per determinare che si tratta di un puntatore tipo stringa LPWSTR
in COM e che pertanto è stato assegnato utilizzando CoTaskMemAlloc()
. Dopo aver creato una stringa gestita dai dati, chiamerà lo CoTaskMemFree()
sul buffer originale per conto dell'utente. I dati che riceverai saranno completamente gestiti e non dovrai affrontare alcun problema di proprietà.
fonte
2011-11-20 04:15:50
Cerca di lavorare con il tipo dinamico con COM Interop - questo può rendere le cose molto più semplici della tipizzazione statica e si occupa anche della gestione della memoria. – weismat
Hai qualche riferimento per l'ultimo bit? C# esegue già la gestione della memoria per l'interoperabilità COM, e lo ha sempre fatto. I tipi dinamici rendono le cose più facili quando si tratta, ad esempio, di un'interfaccia IDispatch, ma hanno effettivamente caratteristiche di gestione della memoria diverse rispetto ai tipi di interoperabilità statici? –