问题
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