IntPtr和避免不安全代码

7

我有一个接受IntPtr参数的外部库。 有没有安全的方法来做到这一点...

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

如何在不使用“不安全”代码的情况下实现这一点?我对IntPtr不是很熟悉,但我想做类似于以下内容的操作:

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

希望以某种方式实现不需要使用/unsafe编译。

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

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


"ref int" 在运行时会产生一个 IntPtr。只需更改 P/Invoke 声明即可。 - Hans Passant
3个回答

3

我认为Output.WriteBytes是一个[DllImport]方法。你能发一下声明吗?

你可以通过将最后一个参数声明为out int而不是IntPtr来避免指针——让P/Invoke marshaller处理剩下的部分。


2

是的,有办法。您可以使用P/Invoke来编写代码。它会自动为您创建指针。类似于这样:

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

(我添加了数组作为奖励)。有关P/Invoke的更多信息,以及无数示例,请访问pinvoke.net

上述每个参数都可以使用outinref。Out和ref参数被翻译为指针,其中ref参数是双向的。


感谢你和Tim,我知道这只是一些简单的东西。 - Aric TenEyck

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

不错,如果您不能使用 DllImport。 一些有兴趣的人背景:http://www.informit.com/guides/content.aspx?g=dotnet&seqNum=543。 关于网络礼仪的说明:如果您从其他网站复制/粘贴而不是自己发明,请确保包含指向源的链接:http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/f74b7c3c-12c4-466b-9754-82e9dea8b83e - Abel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接