Come può essere utilizzato un Safehandle in una firma P/invoca che richiede un puntatore nullo in alcuni casi?
Domanda
Spero che questo non sia troppo oscuro per così, ma considera la seguente firma P/invoca:
[DllImport("odbc32.dll", CharSet = CharSet.Unicode)]
internal static extern OdbcResult SQLAllocHandle(
OdbcHandleType HandleType,
IntPtr InputHandle,
ref IntPtr OutputHandlePtr);
Vorrei riprogettare questa firma per usare Safehandles, come segue:
[DllImport("odbc32.dll", CharSet = CharSet.Unicode)]
internal static extern OdbcResult SQLAllocHandle(
OdbcHandleType HandleType,
MySafeHandle InputHandle,
ref MySafeHandle OutputHandlePtr);
Tuttavia, Secondo MSDN, l'argomento inputhandle deve essere un puntatore nullo quando l'argomento manuale è SQL_HANDLE_ENV e un puntatore non null altrimenti.
Come posso catturare quelle semantiche in una singola firma P/invoca? Si prega di includere un esempio di chiamata nella tua risposta. La mia soluzione attuale è quella di utilizzare due firme.
Soluzione
SafeHandle
è una classe quindi dovresti essere in grado di passare null
piuttosto che un vero SafeHandle
. Un riferimento nullo viene mashalizzato come puntatore nullo in p/invochi.
SafeHandle handle = new SafeHandle();
OdbcResult result= SQLAllocHandle(OdbcHandleType.SQL_HANDLE_ENV, null, ref handle);
Altri suggerimenti
La risposta di SHF301 passa null
Per l'argomento input InputHandle
. Questo non funziona sulla maggior parte delle API (forse in qualche modo fa per il problema specifico dell'OP, dato che hanno accettato la risposta).
Uso questo modello:
[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 che posso farlo per passare una maniglia nulla:
SomeApi(RegionHandle.Null);
È simile a come c'è un IntPtr.Zero
Membro statico.