2012-08-15 17 views
13

Ho cercato su internet in lungo e in largo ma non ho trovato una buona spiegazione.Posso usare SafeHandle invece di IntPtr?

La mia domanda è piuttosto semplice.

Ho una DLL che ha una funzione denominata Initialize e uno dei parametri è un puntatore che riceverà un handle da utilizzare con le chiamate successive. Un altro parametro è una stringa che elencherò per completezza. La firma che sto usando è (nella sua forma semplice):

[DllImport(MyDll)] 
static extern bool Initialize([In] string name, out IntPtr handle); 

La firma nella DLL stesso è scritto come: Initialize(LPTSTR name, HANDLE handle) con il commento "MANICO: Puntatore a una posizione che riceverà la maniglia".

e successive chiamate sono in forma di

[DllImport(MyDll)] 
static extern bool DoSomething(IntPtr handle, uint randomParameter); 

ho letto su SafeHandle e mi chiedevo se potevo usarlo per substite per il mio manico IntPtr. E se posso, come lo faccio? Estendere la classe SafeHandle astratta non è un problema, ma posso sostituire direttamente IntPtr per SafeHandle (e utilizzare Marshalling predefinito) o devo fare qualcosa in più?

+0

Quali benefici ha 'SafeHandle' che basta memorizzare il' IntPtr' danno non? –

+4

@ScottChamberlain - 'SafeHandle' è' IDisposable' e garantisce che le risorse cui fa riferimento l'handle vengano rilasciate.'IntPtr' è semplicemente un valore di dimensione puntatore che può essere passato in giro - non ha una semantica di eliminazione. – LBushkin

+0

Supponendo che sia consentito addebitare la memoria, a meno che non sia possibile annullare l'allocazione della memoria del puntatore utilizzando 'Marshal.FreeBSTR',' Marshal.FreeCoTaskMem' o 'Marshal.FreeHGlobal', non penso che si possa tranquillamente de -Allocare la memoria da C#. Usando 'IntPtr', C# non tenterà di liberare automaticamente la memoria. – Pooven

risposta

10

È possibile trovare una risposta più completa circa la differenza tra SafeHandle e IntPtr qui: IntPtr, SafeHandle and HandleRef - Explained

Tuttavia, per riassumere, IntPtr dovrebbe essere usato dove l'argomento è in realtà un puntatore macchina-size-SafeHandle dovrebbe essere utilizzato dove l'argomento è in realtà un handle Win32. Questi tipi non sono generalmente intercambiabili; la dimensione di IntPtr varierà su diverse architetture (32 bit su x86 e 64 bit su x64 e amd64). NOTA: sotto le coperture credo che SafeHandle usi anche un IntPtr).

Inoltre, a differenza di IntPtr, SafeHandle esegue effettivamente lo smaltimento delle risorse quando un tipo è garbage collection. Ciò garantisce che le risorse di sistema non siano trapelate quando il tuo programma è in esecuzione (anche se dovresti telefonare alle istanze SafeHandle in anticipo quando possibile). Si noti che SafeHandle è in realtà astratto perché ci sono molti diversi tipi di maniglie che richiedono approcci diversi per il corretto smaltimento e gestione.

Nel caso specifico, è necessario consultare la documentazione per la DLL che si sta chiamando. Se è una DLL Win32, potrebbe esistere già un tipo SafeHandle. Se si tratta di una DLL di terze parti, è possibile implementare la propria implementazione SafeHandle, presupponendo che oltre a Initialize() ci sia una versione di Release() (o equivalente).

Alcune interessanti curiosità aggiuntive circa IntPtr vs SafeHandle sono disponibili all'indirizzo:

Use SafeHandle to encapsulate native resources

SafeHandle Class Reference

SafeHandles and Critical Finalization

+0

Sicuramente 'IntPtr' è 64 bit non 65? Ho apportato la modifica - per favore ripristina e spiega di più (sono preparato per questo essere la mia "impara qualcosa di nuovo ogni giorno). – sblom

+0

Beh, creare il mio impianto SafeHandle come ho detto non è un grosso problema, ci sono molti esempi Ciò che vorrei sapere è se posso usare SafeHandle e IntPtr intercambiabili, quindi potrei fare: 'static extern bool Initialize ([In] nome stringa, fuori SafeHandle)' invece che l'attuale 'statico extern bool Initialize ([In] string name, out IntPtr) '? – Davio

+0

@sblom: No, quello era solo un errore di battitura da parte mia.Grazie per averlo preso. – LBushkin

Problemi correlati