如何从 C# 中的 byte[] 获取 IntPtr
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/537573/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get IntPtr from byte[] in C#
提问by netseng
I want to pass a byte[]
to a method takes a IntPtr
Parameter in C#, is that possible and how?
我想将byte[]
一个方法传递给一个IntPtr
在 C# 中需要一个参数的方法,这可能吗?怎么做?
采纳答案by Richard Szalay
Not sure about getting an IntPtr to an array, but you can copy the data for use with unmanaged code by using Mashal.Copy:
不确定将 IntPtr 获取到数组,但您可以使用 Mashal.Copy 复制数据以用于非托管代码:
IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length);
// Call unmanaged code
Marshal.FreeHGlobal(unmanagedPointer);
Alternatively you could declare a struct with one property and then use Marshal.PtrToStructure, but that would still require allocating unmanaged memory.
或者,您可以声明一个具有一个属性的结构,然后使用 Marshal.PtrToStructure,但这仍然需要分配非托管内存。
Edit:Also, as Tyalis pointed out, you can also use fixedif unsafe code is an option for you
编辑:另外,正如 Tyalis 指出的,如果不安全代码是您的一个选项,您也可以使用固定
回答by Micha?l Carpentier
This should work but must be used within an unsafe context:
这应该有效,但必须在不安全的上下文中使用:
byte[] buffer = new byte[255];
fixed (byte* p = buffer)
{
IntPtr ptr = (IntPtr)p;
// do you stuff here
}
beware, you have to use the pointer in the fixed block! The gc can move the object once you are not anymore in the fixed block.
当心,您必须在固定块中使用指针!一旦您不再处于固定块中,gc 就可以移动对象。
回答by user65157
Another way,
其它的办法,
GCHandle pinnedArray = GCHandle.Alloc(byteArray, GCHandleType.Pinned);
IntPtr pointer = pinnedArray.AddrOfPinnedObject();
// Do your stuff...
pinnedArray.Free();
回答by Alejandro Mezcua
In some cases you can use an Int32 type (or Int64) in case of the IntPtr. If you can, another useful class is BitConverter. For what you want you could use BitConverter.ToInt32 for example.
在某些情况下,您可以在 IntPtr 的情况下使用 Int32 类型(或 Int64)。如果可以,另一个有用的类是 BitConverter。对于你想要的,你可以使用 BitConverter.ToInt32 例如。
回答by Sakthi
You could use Marshal.UnsafeAddrOfPinnedArrayElement(array, 0)
to get a memory pointer to the array.
您可以使用Marshal.UnsafeAddrOfPinnedArrayElement(array, 0)
来获取指向数组的内存指针。
回答by David Burg
Marshal.Copy works but is rather slow. Faster is to copy the bytes in a for loop. Even faster is to cast the byte array to a ulong array, copy as much ulong as fits in the byte array, then copy the possible remaining 7 bytes (the trail that is not 8 bytes aligned). Fastest is to pin the byte array in a fixed statement as proposed above in Tyalis' answer.
Marshal.Copy 有效,但速度相当慢。更快的是在 for 循环中复制字节。更快的是将字节数组转换为 ulong 数组,复制适合字节数组的尽可能多的 ulong,然后复制可能剩余的 7 个字节(不是 8 个字节对齐的尾迹)。最快的是将字节数组固定在上面 Tyalis 的回答中提出的固定语句中。
回答by dlchambers
Here's a twist on @user65157's answer (+1 for that, BTW):
这是@ user65157 答案的一个转折(顺便说一句,+1):
I created an IDisposable wrapper for the pinned object:
我为固定对象创建了一个 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();
}
}
then use it like thusly:
然后像这样使用它:
using (AutoPinner ap = new AutoPinner(MyManagedObject))
{
UnmanagedIntPtr = ap; // Use the operator to retrieve the IntPtr
//do your stuff
}
I found this to be a nice way of not forgetting to call Free() :)
我发现这是一个不错的方法,不会忘记调用 Free() :)