Come può essere utilizzato un Safehandle in una firma P/invoca che richiede un puntatore nullo in alcuni casi?

StackOverflow https://stackoverflow.com/questions/8370016

  •  27-10-2019
  •  | 
  •  

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.

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top