从IntPtr(16位)数组复制到托管的ushort
我有一个名为rawbits的IntPtr,它指向一个10MB的数据数组,16位值。 我需要从中返回一个托管的ushort数组。 以下代码有效,但我想摆脱一个额外的BlockCopy。 Marshal.Copy不支持ushort。 我能做什么? (仅供参考:rawbits由videoframegrabber卡填充到非托管内存中)
public const int width = 2056; public const int height = 2048; public const int depth = 2; public System.IntPtr rawbits; public ushort[] bits() { ushort[] output = new ushort[width * height]; short[] temp = new short[width * height]; Marshal.Copy(rawbits, temp, 0, width * height); System.Buffer.BlockCopy(temp, 0, output, 0, width * height * depth); return output; }
以下问题中给出的建议没有帮助。 (编译错误)。
C#Marshal.Copy Intptr到16位托管无符号整数数组
[顺便说一句,短arrays中确实有无符号的16位数据。 Marshal.Copy()不尊重标志,这就是我想要的。 但我宁愿不只是假装短[]是一个ushort []]
选项1 – 调用CopyMemory
:
[DllImport("kernel32.dll", SetLastError = false)] static extern void CopyMemory(IntPtr destination, IntPtr source, UIntPtr length); public static void Copy(IntPtr source, T[] destination, int startIndex, int length) where T : struct { var gch = GCHandle.Alloc(destination, GCHandleType.Pinned); try { var targetPtr = Marshal.UnsafeAddrOfPinnedArrayElement(destination, startIndex); var bytesToCopy = Marshal.SizeOf(typeof(T)) * length; CopyMemory(targetPtr, source, (UIntPtr)bytesToCopy); } finally { gch.Free(); } }
不便携,但性能不错。
选项2 – unsafe
和指针:
public static void Copy(IntPtr source, ushort[] destination, int startIndex, int length) { unsafe { var sourcePtr = (ushort*)source; for(int i = startIndex; i < startIndex + length; ++i) { destination[i] = *sourcePtr++; } } }
需要在项目构建属性中启用unsafe
选项。
选项3 - 反思(只是为了好玩, 不要在生产中使用 ):
Marshal
类在内部对所有Copy(IntPtr,
重载(至少在.NET 4.5中)使用CopyToManaged(IntPtr, object, int, int)
方法。 使用reflection我们可以直接调用该方法:
private static readonly Action _copyToManaged = GetCopyToManagedMethod(); private static Action GetCopyToManagedMethod() { var method = typeof(Marshal).GetMethod("CopyToManaged", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic); return (Action)method.CreateDelegate( typeof(Action), null); } public static void Copy(IntPtr source, T[] destination, int startIndex, int length) where T : struct { _copyToManaged(source, destination, startIndex, length); }
由于Marshal
类的内部结构可以更改,因此该方法不可靠且不应使用,但此实现可能最接近其他Marshal.Copy()
方法重载。
好像你自己做了额外的转换(短[[]到ushort [],你基本上已经做过),或者通过unsafe关键字自己做mem复制。
还有第三种选择:创建自定义结构。
struct MyMagicalStruct { // todo: set SizeConst correct [MarshalAs(UnmanagedType.ByValArray, SizeConst=width*height)] public ushort[] Test123; }
您还必须使用Marshal.PtrToStructure
..
上述就是C#学习教程:从IntPtr(16位)数组复制到托管的ushort分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注---计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1016621.html