6

我有一个采用 IntPtr 的外部库。有什么安全的方法可以做到这一点...

int BytesWritten = 0;
Output.WriteBytes(buffer, new IntPtr(&BytesWritten));

...无需使用“不安全”代码?我对 IntPtrs 不太熟悉,但我想做这样的事情:

fixed int BytesWritten = 0;
Output.WriteBytes(buffer, IntPtr.GetSafeIntPtr(ref BytesWritten));

...以这样一种方式,我不需要使用 /unsafe 进行编译。

我无法更改 WriteBytes 函数,它是一个外部函数。

'ref int' 和 IntPtr 之间似乎应该有某种类型的转换,但我没有找到它的运气。

4

3 回答 3

3

我认为这Output.WriteBytes是一种[DllImport]方法。可以发声明吗?

您应该能够通过将最后一个参数声明为out int而不是IntPtr-- 让 P/Invoke 编组器完成其余的工作来避免指针。

于 2010-07-26T17:43:19.153 回答
2

就在这里。您可以将 P/Invoke 用于您的代码。它将自动为您创建指针。像这样的东西:

[DllImport("yourlib", SetLastError=true)]
static extern bool WriteBytes(
    [MarshalAs(UnmanagedType.LPArray)]
    byte [] buffer,
    ref int BytesWritten);

(我添加了数组作为奖励)。可以在pinvoke.net找到有关 P/Invoke 的更多信息以及大量示例。

上面的每个参数都可以采用out,inref. Out 和 ref 参数被转换为指针,其中 ref 参数是双向的。

于 2010-07-26T17:41:36.593 回答
1

这是一个将为您提供安全 IntPtr 实现的类。它派生自 .NET 框架提供的 SafeHandleZeroOrMinusOneIsInvalid 类。

/// <summary>
/// IntPtr wrapper which can be used as result of
/// Marshal.AllocHGlobal operation.
/// Call Marshal.FreeHGlobal when disposed or finalized.
/// </summary>
class HGlobalSafeHandle : SafeHandleZeroOrMinusOneIsInvalid
{
    /// <summary>
    /// Creates new instance with given IntPtr value
    /// </summary>
    public HGlobalSafeHandle(IntPtr ptr) : base(ptr, true)
    {
    }

    /// <summary>
    /// Creates new instance with zero IntPtr
    /// </summary>
    public HGlobalSafeHandle() : base(IntPtr.Zero, true)
    {
    }

    /// <summary>
    /// Creates new instance which allocates unmanaged memory of given size 

  /// Can throw OutOfMemoryException
    /// </summary>
    public HGlobalSafeHandle(int size) :
        base(Marshal.AllocHGlobal(size), true)
    {
    }


    /// <summary>
    /// Allows to assign IntPtr to HGlobalSafeHandle
    /// </summary>
    public static implicit operator HGlobalSafeHandle(IntPtr ptr)
    {
        return new HGlobalSafeHandle(ptr);
    }

    /// <summary>
    /// Allows to use HGlobalSafeHandle as IntPtr
    /// </summary>
    public static implicit operator IntPtr(HGlobalSafeHandle h)
    {
        return h.handle;
    }

    /// <summary>
    /// Called when object is disposed or finalized.
    /// </summary>
    override protected bool ReleaseHandle()
    {
        Marshal.FreeHGlobal(handle);
        return true;
    }

    /// <summary>
    /// Defines invalid (null) handle value.
    /// </summary>
    public override bool IsInvalid
    {
        get
        {
            return (handle == IntPtr.Zero);
        }
    }
}
于 2010-07-26T17:47:04.430 回答