简体   繁体   English

IntPtr并避免不安全的代码

[英]IntPtr and avoiding unsafe code

I have an external library that takes an IntPtr. 我有一个带IntPtr的外部库。 Is there any safe way to do this... 有没有安全的方法来做到这一点......

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

...without having to use 'unsafe' code? ...而不必使用'不安全'代码? I'm not that familiar with IntPtrs, but I'd like to do something like this: 我对IntPtrs并不熟悉,但我想做这样的事情:

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

...in such a way that I don't need to compile with /unsafe. ......以这种方式我不需要编译/不安全。

I can't change the WriteBytes function, it's an external function. 我不能改变WriteBytes函数,它是一个外部函数。

It seems like there should be some sort of cast between 'ref int' and IntPtr, but I have not had luck finding it. 似乎应该在'ref int'和IntPtr之间进行某种转换,但我没有找到它的运气。

Yes, there is. 就在这里。 You can use P/Invoke for your code. 您可以使用P / Invoke代码。 It will create the pointer for you automagically. 它会自动为您创建指针。 Something like this: 像这样的东西:

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

(I added the array as a bonus) . (我添加了阵列作为奖励) More info on P/Invoke can be found, with gazillion examples, at pinvoke.net . 有关P / Invoke的更多信息,可以在pinvoke.net找到很多例子。

Each parameter above can take out , in and ref . 上面的每个参数都可以outinref Out and ref parameters are translated as pointers, where an ref-parameter is two-way. Out和ref参数被转换为指针,其中ref参数是双向的。

I assume that Output.WriteBytes is a [DllImport] method. 我假设Output.WriteBytes[DllImport]方法。 Can you post the declaration? 你可以发表声明吗?

You should be able to avoid the pointer by declaring the last parameter as out int instead of IntPtr -- let the P/Invoke marshaller do the rest. 你应该能够通过将最后一个参数声明为out int而不是IntPtr来避免指针 - 让P / Invoke marshaller完成剩下的工作。

Here is a class that will provide you with a safe IntPtr implementation. 这是一个为您提供安全的IntPtr实现的类。 It derives from the SafeHandleZeroOrMinusOneIsInvalid class, provided by the .NET framework. 它派生自.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);
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM