2012-08-15 17 views
13

He buscado en Internet por todas partes pero no encontré una buena explicación.¿Puedo usar SafeHandle en lugar de IntPtr?

Mi pregunta es bastante simple.

Tengo un archivo DLL que tiene una función llamada Inicializar y uno de los parámetros es un puntero que recibirá un identificador para ser utilizado con las llamadas siguientes. Otro parámetro es una cadena que enumeraré para completar. La firma que estoy usando es (en su forma simple):

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

la firma en el propio archivo DLL se escribe como: Initialize(LPTSTR name, HANDLE handle) con el comentario "MANGO: Puntero a una ubicación que recibirá el mango".

y posterior llamadas están en la forma de

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

He estado leyendo sobre SafeHandle y me preguntaba si podría utilizarlo para substite para mi mango IntPtr. Y si puedo, ¿cómo lo hago? La extensión de la clase abstracta SafeHandle no es un problema, pero ¿puedo sustituir directamente mi IntPtr por SafeHandle (y usar Marshalling predeterminado) o necesito hacer algo extra?

+0

qué beneficios 'SafeHandle' usted que acaba de almacenar el' IntPtr' dan ¿no? –

+4

@ScottChamberlain - 'SafeHandle' es' IDisposable' y garantiza que se liberen los recursos a los que hace referencia el identificador.'IntPtr' es simplemente un valor del tamaño de un puntero que se puede pasar: no tiene semántica de eliminación. – LBushkin

+0

Suponiendo que se le permite cargar la memoria, a menos que pueda desasignar la memoria del puntero usando 'Marshal.FreeBSTR',' Marshal.FreeCoTaskMem', o 'Marshal.FreeHGlobal', no creo que pueda -alcanzar la memoria desde C#. Usando 'IntPtr', C# no intentará liberar memoria automáticamente. – Pooven

Respuesta

10

puede encontrar una respuesta más completa sobre la diferencia entre SafeHandle y IntPtr aquí: IntPtr, SafeHandle and HandleRef - Explained

Sin embargo, para resumir, IntPtr deberán utilizarse cuando el argumento es en realidad un puntero máquina de tamaño - SafeHandle debe ser usado donde el argumento es realmente un manejador de Win32. Estos tipos generalmente no son intercambiables; el tamaño de IntPtr variará según las diferentes arquitecturas (32 bits en x86 y 64 bits en x64 y amd64). NOTA: Debajo de las fundas, creo que SafeHandle también usa IntPtr).

Además, a diferencia de IntPtr, SafeHandle en realidad realiza la eliminación de recursos cuando se recolecta un tipo de basura. Esto garantiza que los recursos del sistema no se filtren cuando su programa se está ejecutando (aunque debe realizar Dispose() de SafeHandle instancias anticipadas cuando sea posible). Tenga en cuenta que SafeHandle es realmente abstracto porque hay muchos tipos diferentes de asas que requieren diferentes enfoques para la eliminación y el manejo adecuados.

En su caso específico, debe consultar la documentación del archivo DLL al que está llamando. Si se trata de una DLL Win32, es posible que ya haya un tipo SafeHandle para ella. Si se trata de una DLL de terceros, puede implementar su propia implementación de SafeHandle, suponiendo que además de Initialize(), haya alguna versión de Release() (o equivalente).

Algunos datos interesantes adicionales sobre IntPtr vs SafeHandle se puede encontrar en:

Use SafeHandle to encapsulate native resources

SafeHandle Class Reference

SafeHandles and Critical Finalization

+0

Seguramente 'IntPtr' es 64 bits, no 65? Hice la edición - invierta y explique más (estoy preparado para que este sea mi "aprender algo nuevo todos los días") – sblom

+0

Bueno, crear mi propia implementación de SafeHandle como dije no es gran cosa, hay muchos ejemplos Lo que me gustaría saber es si puedo usar SafeHandle e IntPtr intercambiables, así podría hacer: 'static ext. bool Initialize ([In] string name, out SafeHandle)' en lugar del actual 'static extern bool Initialize ([In] string name, out IntPtr) '? – Davio

+0

@sblom: No, eso fue solo un error tipográfico por mi parte. Gracias por atraparlo – LBushkin