Comment un SafeHandle peut être utilisé dans une signature P / Invoke qui nécessite un pointeur NULL dans certains cas?

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

  •  27-10-2019
  •  | 
  •  

Question

Espérons que cela ne soit pas trop obscur pour le SO, mais considère ce qui suit la signature P / Invoke:

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

Je voudrais redessiner cette signature à SafeHandles d'utilisation, comme suit:

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

Cependant, selon MSDN , l'argument InputHandle doit être un pointeur null lorsque l'argument HandleType est SQL_HANDLE_ENV et un pointeur non nul par ailleurs.

Comment capturer cette sémantique dans un seul P / Invoke signature? S'il vous plaît inclure un appel-site par exemple dans votre réponse. Ma solution actuelle est d'utiliser deux signatures.

Était-ce utile?

La solution

SafeHandle est une classe de sorte que vous devriez être en mesure de passer null plutôt que d'une réelle SafeHandle. Une référence nulle est assemblée comme un pointeur null P / Invoke.

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

Autres conseils

La réponse par shf301 passe null pour l'argument d'entrée InputHandle. Cela ne fonctionne pas sur la plupart des API (peut-être le fait d'une certaine manière pour le problème spécifique de l'OP, étant donné qu'ils ont accepté la réponse).

J'utilise ce modèle:

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

Cela signifie que je peux le faire pour passer une poignée nulle:

SomeApi(RegionHandle.Null);

Il est similaire à la façon dont il est un membre statique IntPtr.Zero.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top