8

希望这对 SO 来说不是太晦涩难懂,但请考虑以下 P/Invoke 签名:

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

我想重新设计此签名以使用 SafeHandles,如下所示:

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

但是,根据 MSDN,当 HandleType 参数为 SQL_HANDLE_ENV 时 InputHandle 参数必须为空指针,否则为非空指针。

如何在单个 P/Invoke 签名中捕获这些语义?请在您的答案中包含一个示例呼叫站点。我目前的解决方案是使用两个签名。

4

2 回答 2

3

SafeHandle是一门课,所以你应该能够通过null而不是实际的SafeHandle. 空引用在 P/Invoke 中被封送为空指针。

SafeHandle handle = new SafeHandle();
OdbcResult result= SQLAllocHandle(OdbcHandleType.SQL_HANDLE_ENV, null, ref handle);
于 2011-12-03T18:50:25.697 回答
2

shf301 的答案传递null给输入参数InputHandle。这在大多数 API 上都不起作用(也许它以某种方式对 OP 的特定问题起作用,因为他们接受了答案)。

我使用这种模式:

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

这意味着我可以这样做来传递一个空句柄:

SomeApi(RegionHandle.Null);

这类似于有一个IntPtr.Zero静态成员。

于 2013-12-09T18:07:54.043 回答