c# – 从IntPtr(16位)数组复制到托管的ushort

我有一个名为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()方法重载.

相关文章

在要实现单例模式的类当中添加如下代码:实例化的时候:frmC...
1、如果制作圆角窗体,窗体先继承DOTNETBAR的:public parti...
根据网上资料,自己很粗略的实现了一个winform搜索提示,但是...
近期在做DSOFramer这个控件,打算自己弄一个自定义控件来封装...
今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都...
最近在研究WinWordControl这个控件,因为上级要求在系统里,...