如何从C#中的byte []获取IntPtr

net*_*eng 122 .net c#

我想传递一个byte[]方法IntPtr在C#中接受一个参数,这是可能的,怎么样?

小智 198

其他方式,

GCHandle pinnedArray = GCHandle.Alloc(byteArray, GCHandleType.Pinned);
IntPtr pointer = pinnedArray.AddrOfPinnedObject();
// Do your stuff...
pinnedArray.Free();
Run Code Online (Sandbox Code Playgroud)

  • @ makerofthings7我不相信Lippert说使用'固定'而不是GC [固定对象],我相信他说不要使用GC无限期地固定一个对象,并说不要使用固定来做同样的. (6认同)
  • @piggy:我认为Marshal的缺点是你必须复制你的数据(这可能需要很长时间并浪费你可能需要的内存) (3认同)

Mic*_*ier 122

这应该工作但必须在不安全的环境中使用:

byte[] buffer = new byte[255];
fixed (byte* p = buffer)
{
    IntPtr ptr = (IntPtr)p;
    // do you stuff here
}
Run Code Online (Sandbox Code Playgroud)

要注意,你必须使用固定块中的指针!一旦你不再在固定块中,gc就可以移动对象.

  • 我喜欢这个答案,因为它不涉及分配额外的内存只是为了访问数据 (15认同)
  • 如果使用大字节[],这是最好的答案.副本有太多开销 (3认同)

Ric*_*lay 88

不确定将IntPtr添加到数组,但是您可以使用Mashal.Copy复制数据以用于非托管代码:

IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length);
// Call unmanaged code
Marshal.FreeHGlobal(unmanagedPointer);
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用一个属性声明一个结构,然后使用Marshal.PtrToStructure,但这仍然需要分配非托管内存.

编辑:另外,正如Tyalis指出的那样,如果不安全的代码是你的选择,你也可以使用固定的


小智 18

您可以使用Marshal.UnsafeAddrOfPinnedArrayElement(array, 0)获取指向数组的内存指针.

  • 要使这个代码可靠的数组应首先固定http://msdn.microsoft.com/en-us/library/3k4y07x3.aspx (5认同)
  • 这是 - 我认为 - 为不是第 0 个(不使用不安全代码)的数组元素获取 IntPtr 的唯一方法。 (2认同)

dlc*_*ers 13

这是@ user65157的回答(+1为此,BTW):

我为固定对象创建了一个IDisposable包装器:

class AutoPinner : IDisposable
{
   GCHandle _pinnedArray;
   public AutoPinner(Object obj)
   {
      _pinnedArray = GCHandle.Alloc(obj, GCHandleType.Pinned);
   }
   public static implicit operator IntPtr(AutoPinner ap)
   {
      return ap._pinnedArray.AddrOfPinnedObject(); 
   }
   public void Dispose()
   {
      _pinnedArray.Free();
   }
}
Run Code Online (Sandbox Code Playgroud)

然后像这样使用它:

using (AutoPinner ap = new AutoPinner(MyManagedObject))
{
   UnmanagedIntPtr = ap;  // Use the operator to retrieve the IntPtr
   //do your stuff
}
Run Code Online (Sandbox Code Playgroud)

我发现这是一个很好的方式,不要忘记调用Free():)

  • 您可能希望调查从SafeHandle派生AutoPinner,因为该类考虑了并发性和安全性"陷阱",以及鼓励/使用推荐的IDisposable模式. (4认同)