C# Marshal.Copy Intptr to 16 bit managed unsigned integer array

浪尽此生 提交于 2019-12-23 17:09:35

问题


Why does C# Marshal.Copy routine does not have any overload for copying from unmanaged memory pointer to 16 bit managed unsigned integer array?

ex:

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.

If there is no marshalling alternative, how do I copy unmanaged ushort array to managed ushort array?


回答1:


Using unsafe code:

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);

Can be easily adapted to copy uint[] and ulong[] (adjust the number of bytes per element)




回答2:


I think Marshal doesn't have a Copy(IntPtr, UInt16[], Int32, Int32) overload because of CLS compliance (a tenet of CLS compliance is that unsigned integer operations are not exposed to consumers, I disagree with this rule FWIW).

With marshalling, all that matters is the size of the elements. Signed-ness is just a secondary concern. I would either use the Byte or Int16 overloads and do my own casting afterwards, or I would use unsafe pointers.

IntPtr unmanagedArray = ...

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

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



回答3:


Probably because not all managed languages have unsigned types. I don't think that is a good reason, but it's a reasonable explanation.

A cast should work before the unsigned array parameter.

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


来源:https://stackoverflow.com/questions/20981551/c-sharp-marshal-copy-intptr-to-16-bit-managed-unsigned-integer-array

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!