C#Marshal.Copy Intptr到16位托管无符号整数数组

时间:2014-01-07 20:47:09

标签: c# marshalling

为什么C#Marshal.Copy例程没有任何重载从非托管内存指针复制到16位托管无符号整数数组?

例如:

Copy(IntPtr, Byte[], Int32, Int32)  Copies data from an unmanaged memory pointer to a managed 8-bit unsigned integer array.
Copy(IntPtr, Char[], Int32, Int32)  Copies data from an unmanaged memory pointer to a managed character array.
Copy(IntPtr, Double[], Int32, Int32)    Copies data from an unmanaged memory pointer to a managed double-precision floating-point number array.
Copy(IntPtr, Int16[], Int32, Int32) Copies data from an unmanaged memory pointer to a managed 16-bit signed integer array.
Copy(IntPtr, Int32[], Int32, Int32) Copies data from an unmanaged memory pointer to a managed 32-bit signed integer array.
Copy(IntPtr, Int64[], Int32, Int32) Copies data from an unmanaged memory pointer to a managed 64-bit signed integer array.
Copy(IntPtr, IntPtr[], Int32, Int32)    Copies data from an unmanaged memory pointer to a managed IntPtr array.
Copy(IntPtr, Single[], Int32, Int32).   Copies data from an unmanaged memory pointer to a managed single-precision floating-point number array.

如果没有编组替代方法,如何将非托管ushort数组复制到托管的ushort数组?

3 个答案:

答案 0 :(得分:1)

使用不安全的代码:

public static unsafe void Copy(IntPtr ptrSource, ushort[] dest, uint elements) {
  fixed(ushort* ptrDest = &dest[0]) {
     CopyMemory((IntPtr)ptrDest, ptrSource, elements * 2);    // 2 bytes per element
  }
}

public static unsafe void Copy(ushort[] source, Intptr ptrDest, uint elements) {
  fixed(ushort* ptrSource = &source[0]) {
     CopyMemory(ptrDest, (Intptr)ptrSource, elements * 2);    // 2 bytes per element
  }
}

[DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)]
static extern void CopyMemory(IntPtr Destination, IntPtr Source, uint Length);

可以很容易地适应复制uint []和ulong [](调整每个元素的字节数)

答案 1 :(得分:0)

认为 Marshal由于符合CLS而没有Copy(IntPtr, UInt16[], Int32, Int32)重载(CLS合规性的一个原则是无符号整数操作不向消费者公开,I不同意这条规则FWIW)。

通过编组,重要的是元素的大小。签名只是次要问题。我会使用ByteInt16重载并在之后进行自己的转换,或者我会使用不安全的指针。

IntPtr unmanagedArray = ...

Int16[] destination0 = new Int16[ count ];
Marshal.Copy( unmanagedArray, destination0, 0, count );

UInt16[] destinion1 = destination0.OfType<UInt16>().ToArray(); // Linq extension method

答案 2 :(得分:-1)

可能是因为并非所有托管语言都有无符号类型。我不认为这是一个很好的理由,但这是一个合理的解释。

强制转换应该在无符号数组参数之前工作。

Copy(addr, (Int16[])someUnsignedArray, 0, len);