如何从C#中的字节获取IntPtr
我想传递一个byte[]
给一个方法在C#中需要一个IntPtr
参数,这是可能的,怎么样?
不知道获取一个IntPtr到一个数组,但您可以通过使用Mashal.Copy复制数据与非托pipe代码一起使用:
IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length); Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length); // Call unmanaged code Marshal.FreeHGlobal(unmanagedPointer);
或者,你可以声明一个结构与一个属性,然后使用Marshal.PtrToStructure,但仍然需要分配非托pipe内存。
编辑:此外,正如Tyalis指出的,如果不安全的代码是一个选项,你也可以使用固定
其他方式,
GCHandle pinnedArray = GCHandle.Alloc(byteArray, GCHandleType.Pinned); IntPtr pointer = pinnedArray.AddrOfPinnedObject(); // Do your stuff... pinnedArray.Free();
这应该工作,但必须在不安全的情况下使用:
byte[] buffer = new byte[255]; fixed (byte* p = buffer) { IntPtr ptr = (IntPtr)p; // do you stuff here }
当心,你必须使用固定块中的指针! 一旦你不在固定块中,gc就可以移动对象。
你可以使用Marshal.UnsafeAddrOfPinnedArrayElement(array, 0)
来获得一个指向数组的内存指针。
下面是@ user65157的答案(对此为+1)的转折:
我为该固定对象创build了一个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(); } }
然后像这样使用它:
using (AutoPinner ap = new AutoPinner(MyManagedObject)) { UnmanagedIntPtr = ap; // Use the operator to retrieve the IntPtr //do your stuff }
我发现这是一个不忘记打电话给Free()的好方法:)
元帅。复制工作,但相当缓慢。 更快的是复制for循环中的字节。 甚至更快的是将字节数组转换为ulong数组,复制尽可能多的ulong以适应字节数组,然后复制可能剩余的7个字节(不是8个字节alignment的轨迹)。 最快的是按照上面在Tyalis的回答中提出的固定语句固定字节数组。
在某些情况下,您可以在IntPtr的情况下使用Int32types(或Int64)。 如果可以,另一个有用的类是BitConverter。 对于你想要的,你可以使用BitConverter.ToInt32作为例子。