代码之家  ›  专栏  ›  技术社区  ›  Aric TenEyck

intptr和避免不安全代码

  •  4
  • Aric TenEyck  · 技术社区  · 14 年前

    我有一个接受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之间应该有某种类型的强制转换,但我找不到它。

    3 回复  |  直到 14 年前
        1
  •  2
  •   Abel    14 年前

    是的,有。您可以对代码使用p/invoke。它将自动为您创建指针。像这样:

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

    (我添加了阵列作为奖励) . 有关p/invoke的更多信息,请参阅gazillion示例,网址: pinvoke.net .

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

        2
  •  2
  •   Tim Robinson    14 年前

    我认为 Output.WriteBytes 是一个 [DllImport] 方法。你能邮寄申报单吗?

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

        3
  •  1
  •   Icemanind    14 年前

    下面是一个类,它将为您提供一个安全的intptr实现。它派生自.NET框架提供的SafeHandleZeroOrMinusOneSonisInvalid类。

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