2010-07-26 102 views
4

我有一个外部库需要一个IntPtr。是否有任何安全的方法来做到这一点...IntPtr和避免不安全的代码

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

......不必使用'不安全'的代码?我没那么熟悉IntPtrs,但我喜欢做这样的事情:

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

......在这样的,我不需要用/不安全编译的方式。

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

似乎应该在'ref int'和IntPtr之间进行某种转换,但是我没有找到它。

+0

“ref int”在运行时产生一个IntPtr。只需更改P/Invoke声明。 – 2010-07-26 19:19:57

回答

2

是的,有。您可以使用P/Invoke代码。它会自动为你创建指针。是这样的:

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

(I加入所述阵列作为奖金)。更多关于P/Invoke的信息可以在pinvoke.net的gazillion例子中找到。

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

+0

感谢你和Tim;我知道这会是一件简单的事情。 – 2010-07-26 22:07:01

2

我假定Output.WriteBytes是一个[DllImport]方法。你能发表声明吗?

您应该可以通过声明最后一个参数为out int而不是IntPtr - 让P/Invoke编组人完成剩下的工作,以避免指针。

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

不错,如果你不能使用'DllImport'。感兴趣的一些背景:http://www.informit.com/guides/content.aspx?g=dotnet&seqNum=543。网络礼仪注意事项:如果您从其他网站复制/粘贴并且没有自己创作,请务必将链接添加到您的源代码中:http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/线程/ f74b7c3c-12c4-466b-9754-82e9dea8b83e – Abel 2010-07-26 17:50:02