2012-08-15 14 views
13

Ich habe das Internet weit und breit gesucht, aber keine gute Erklärung gefunden.Kann ich SafeHandle anstelle von IntPtr verwenden?

Meine Frage ist ziemlich einfach.

Ich habe eine DLL, die eine Funktion namens Initialize hat und einer der Parameter ist ein Zeiger, der ein Handle erhalten wird, um mit nachfolgenden Aufrufen verwendet zu werden. Ein weiterer Parameter ist ein String, den ich zur Vollständigkeit auflisten werde. Die Unterschrift Ich verwende ist (in seiner einfachen Form):

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

Die Signatur in der DLL selbst geschrieben als: Initialize(LPTSTR name, HANDLE handle) mit dem Kommentar „HANDLE: Pointer auf eine Stelle, die den Griff bekommt“.

Und nachfolgende Aufrufe sind in Form von

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

Ich habe über SafeHandle lesen, und ich habe mich gefragt, ob ich es für meinen IntPtr Griff substite nutzen könnte. Und wenn ich kann, wie mache ich das? Das Erweitern der abstrakten SafeHandle-Klasse ist kein Problem, aber kann ich mein IntPtr für SafeHandle direkt ersetzen (und Standard-Marshalling verwenden) oder muss ich etwas extra tun?

+0

Welchen Nutzen hat 'SafeHandle' Sie geben, dass die' IntPtr' nur speichern:

Einige weitere interessante Leckerbissen über IntPtr vs Safehandle finden Sie unter nicht? –

+4

@ScottChamberlain - 'SafeHandle' ist' IDisposable' und stellt sicher, dass Ressourcen, auf die sich das Handle bezieht, freigegeben werden.'IntPtr' ist einfach ein zeigergroßer Wert, der herumgereicht werden kann - er hat keine Entsorgungssemantik. – LBushkin

+0

Angenommen, Sie dürfen den Speicher aufladen, es sei denn, Sie können den Zeigerspeicher mit 'Marshal.FreeBSTR',' Marshal.FreeCoTaskMem' oder 'Marshal.FreeHGlobal' freischalten. Ich glaube nicht, dass Sie das sicher tun können - Weisen Sie den Speicher von C# zu. Mit 'IntPtr' versucht C# nicht, Speicher automatisch zu löschen. – Pooven

Antwort

10

Sie eine vollständigere Antwort über den Unterschied zwischen SafeHandle und IntPtr finden Sie hier: IntPtr, SafeHandle and HandleRef - Explained

jedoch zusammenzufassen, sollte IntPtr verwendet werden, wo das Argument tatsächlich eine Zeiger Maschinengröße ist-SafeHandle sollte verwendet, wo das Argument tatsächlich ein Win32-Handle ist. Diese Typen sind im Allgemeinen nicht austauschbar; Die Größe von IntPtr variiert auf verschiedenen Architekturen (32 Bit auf x86 und 64 Bit auf x64 und amd64). HINWEIS: Unter den Abdeckungen glaube ich SafeHandle verwendet ein IntPtr als auch).

Auch im Gegensatz zu IntPtr, SafeHandle führt tatsächlich die Entsorgung von Ressourcen, wenn ein Typ Müll gesammelt wird. Dies stellt sicher, dass Systemressourcen nicht geleakt werden, wenn Ihr Programm ausgeführt wird (obwohl Sie SafeHandle Instanzen früh, wenn möglich sollten). Beachten Sie, dass SafeHandle eigentlich abstrakt ist, da es viele verschiedene Arten von Griffen gibt, die unterschiedliche Ansätze für eine ordnungsgemäße Entsorgung und Handhabung erfordern.

In Ihrem speziellen Fall müssen Sie die Dokumentation für die DLL aufrufen, die Sie aufrufen. Wenn es sich um eine Win32-DLL handelt, ist möglicherweise bereits ein SafeHandle-Typ vorhanden. Wenn es sich um eine DLL eines Drittanbieters handelt, können Sie Ihre eigene SafeHandle-Implementierung rollen - vorausgesetzt, dass zusätzlich zu Initialize() eine Version von Release() (oder gleichwertig) vorhanden ist.

Use SafeHandle to encapsulate native resources

SafeHandle Class Reference

SafeHandles and Critical Finalization

+0

Sicher 'IntPtr' ist 64 Bits nicht 65? Ich habe den Schnitt gemacht - bitte revert und erläutere mehr (ich bin darauf vorbereitet, dass das mein "jeden Tag etwas Neues lernen soll). – sblom

+0

Nun, meine eigene SafeHandle-Implementierung zu erstellen, wie ich schon sagte, ist keine große Sache, es gibt viele Beispiele Ich würde gerne wissen, ob ich SafeHandle und IntPtr austauschbar verwenden kann, also könnte ich Folgendes tun: 'static extern bool Initialize ([In] String-Name, out SafeHandle)' anstelle des aktuellen 'static extern bool Initialize ([In] string name, aus IntPtr) '? – Davio

+0

@sblom: Nein, das war nur ein Tippfehler von mir. Danke, dass du es geholt hast. – LBushkin