c# – 从IntPtr(16位)数组复制到托管的ushort
发布时间:2020-12-15 08:22:34 所属栏目:百科 来源:网络整理
导读:我有一个名为rawbits的IntPtr,它指向10MB的数据数组,16位值.我需要从中返回一个托管的ushort数组.以下代码有效,但我想摆脱一个额外的BlockCopy. Marshal.Copy不支持ushort.我能做什么? (仅供参考:rawbits由视频framegrabber卡填充到非托管内存中) public c
我有一个名为rawbits的IntPtr,它指向10MB的数据数组,16位值.我需要从中返回一个托管的ushort数组.以下代码有效,但我想摆脱一个额外的BlockCopy. Marshal.Copy不支持ushort.我能做什么? (仅供参考:rawbits由视频framegrabber卡填充到非托管内存中)
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,width * height); System.Buffer.BlockCopy(temp,output,width * height * depth); return output; } 以下问题中给出的建议没有帮助. (编译错误). C# Marshal.Copy Intptr to 16 bit managed unsigned integer array [顺便说一句,短阵列中确实有无符号的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<T>(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 – 不安全和指针: public static void Copy(IntPtr source,ushort[] destination,int length) { unsafe { var sourcePtr = (ushort*)source; for(int i = startIndex; i < startIndex + length; ++i) { destination[i] = *sourcePtr++; } } } 需要在项目构建属性中启用不安全选项. 选项3 – 反思(只是为了好玩,不要在生产中使用): Marshal类在内部对所有Copy(IntPtr,< array>,int,int)重载使用CopyToManaged(IntPtr,object,int)方法(至少在.NET 4.5中).使用反射我们可以直接调用该方法: private static readonly Action<IntPtr,int> _copyToManaged = GetCopyToManagedMethod(); private static Action<IntPtr,int> GetCopyToManagedMethod() { var method = typeof(Marshal).GetMethod("CopyToManaged",System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic); return (Action<IntPtr,int>)method.CreateDelegate( typeof(Action<IntPtr,int>),null); } public static void Copy<T>(IntPtr source,int length) where T : struct { _copyToManaged(source,destination,startIndex,length); } 由于Marshal类的内部结构可以更改,因此该方法不可靠且不应使用,尽管此实现可能最接近其他Marshal.Copy()方法重载. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |