Wie kann ein SaferHandle in einer P/Invoke -Signatur verwendet werden, die in bestimmten Fällen einen Nullzeiger erfordert?

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

  •  27-10-2019
  •  | 
  •  

Frage

Hoffentlich ist dies für SO nicht zu dunkel, aber betrachten Sie die folgende P/Invoke -Signatur:

[DllImport("odbc32.dll", CharSet = CharSet.Unicode)]
internal static extern OdbcResult SQLAllocHandle(
    OdbcHandleType HandleType,
    IntPtr InputHandle,
    ref IntPtr OutputHandlePtr);

Ich möchte diese Signatur für die Verwendung von SafeHandles wie folgt neu gestalten:

[DllImport("odbc32.dll", CharSet = CharSet.Unicode)]
internal static extern OdbcResult SQLAllocHandle(
    OdbcHandleType HandleType,
    MySafeHandle InputHandle,
    ref MySafeHandle OutputHandlePtr);

Jedoch, Laut MSDN, Das Inputhandle-Argument muss ein Nullzeiger sein, wenn das Handletyp-Argument sql_handle_env und sonst ein Nicht-Null-Zeiger ist.

Wie erfasse ich diese Semantik in einer einzigen P/Invoke -Signatur? Bitte geben Sie eine Beispielanruf-Site in Ihre Antwort an. Meine aktuelle Lösung ist es, zwei Signaturen zu verwenden.

War es hilfreich?

Lösung

SafeHandle ist eine Klasse, also sollten Sie in der Lage sein, passieren zu können null eher als eine tatsächliche SafeHandle. Eine Nullreferenz wird als Nullzeiger in P/Invoke marschiert.

SafeHandle handle = new SafeHandle();
OdbcResult result= SQLAllocHandle(OdbcHandleType.SQL_HANDLE_ENV, null, ref handle);

Andere Tipps

Die Antwort von SHF301 geht vorbei null für das Eingabebuch InputHandle. Dies funktioniert nicht bei den meisten APIs (vielleicht tut es irgendwie für das spezifische Problem des OP, da sie die Antwort akzeptiert haben).

Ich benutze dieses Muster:

[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);
    }
}

Es bedeutet, dass ich dies tun kann, um einen Nullgriff zu bestehen:

SomeApi(RegionHandle.Null);

Es ist ähnlich, wie es eine gibt IntPtr.Zero Statisches Mitglied.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top