¿Cómo se puede usar un SafeHandle en una firma P/Invoke que requiere un puntero nulo en ciertos casos?
Pregunta
Esperemos que esto no sea demasiado oscuro para así, pero considere la siguiente firma P/Invoke:
[DllImport("odbc32.dll", CharSet = CharSet.Unicode)]
internal static extern OdbcResult SQLAllocHandle(
OdbcHandleType HandleType,
IntPtr InputHandle,
ref IntPtr OutputHandlePtr);
Me gustaría rediseñar esta firma para usar SafeHandles, de la siguiente manera:
[DllImport("odbc32.dll", CharSet = CharSet.Unicode)]
internal static extern OdbcResult SQLAllocHandle(
OdbcHandleType HandleType,
MySafeHandle InputHandle,
ref MySafeHandle OutputHandlePtr);
Sin embargo, Según MSDN, el argumento de inPuthandle debe ser un puntero nulo cuando el argumento del handletype es sql_handle_env y un puntero no nulo de otra manera.
¿Cómo captura esos semánticos en una sola firma P/Invoke? Incluya un ejemplo de sitio de llamada en su respuesta. Mi solución actual es usar dos firmas.
Solución
SafeHandle
es una clase, por lo que deberías poder pasar null
en lugar de un real SafeHandle
. Una referencia nula se somete a un puntero nulo en P/Invoke.
SafeHandle handle = new SafeHandle();
OdbcResult result= SQLAllocHandle(OdbcHandleType.SQL_HANDLE_ENV, null, ref handle);
Otros consejos
La respuesta de shf301 pases null
Para el argumento de entrada InputHandle
. Esto no funciona en la mayoría de las API (tal vez de alguna manera lo hace para el problema específico del OP, dado que aceptaron la respuesta).
Yo uso este patrón:
[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
public class RegionHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private RegionHandle() : base(true) {}
public static readonly RegionHandle Null = new RegionHandle();
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
override protected bool ReleaseHandle()
{
return Region.DeleteObject(handle);
}
}
Significa que puedo hacer esto para pasar un mango nulo:
SomeApi(RegionHandle.Null);
Es similar a cómo hay un IntPtr.Zero
Miembro estático.