/// <summary> /// Marshals data from an array of managed object to an unmanaged block of memory, /// writes the unmanaged data to <paramref name="offset"/> from given <paramref name="ptr"/>. /// </summary> /// <typeparam name="T">The type of the element of the array.</typeparam> /// <param name="array">An array of managed object.</param> /// <param name="ptr">The unmanaged base address to write, must /// have been allocated of enough memory by the caller.</param> /// <param name="offset">The offset to write to.</param> public static void ArrayToPtr <T>(T[] array, IntPtr ptr, int offset) where T : struct { // 32 bits platform if (IntPtr.Size == sizeof(Int32)) { int ptrValue = ptr.ToInt32() + offset; for (uint i = 0; i < array.Length; i++) { int elementSize = TypeMarshal.GetNativeMemorySize <T>(); SafeIntPtr safePtr = TypeMarshal.ToIntPtr <T>(array[i]); AppendToPtrList(ptr, safePtr); NativeMethods.RtlMoveMemory(new IntPtr(ptrValue), safePtr, (uint)elementSize); ptrValue += elementSize; } } // 64 bits platform else if (IntPtr.Size == sizeof(Int64)) { long ptrValue = ptr.ToInt64() + offset; for (uint i = 0; i < array.Length; i++) { int elementSize = TypeMarshal.GetNativeMemorySize <T>(); SafeIntPtr safePtr = TypeMarshal.ToIntPtr <T>(array[i]); AppendToPtrList(safePtr, safePtr); NativeMethods.RtlMoveMemory(new IntPtr(ptrValue), safePtr, (uint)elementSize); ptrValue += elementSize; } } // not supported else { throw new NotSupportedException("Platform is neither 32 bits nor 64 bits."); } }
// Add a SafeIntPtr to pending release list private static void AppendToPtrList(IntPtr key, SafeIntPtr safeIntPtr) { List <SafeIntPtr> list; if (!ptrList.TryGetValue(key, out list)) { list = new List <SafeIntPtr>(); ptrList.Add(key, list); } list.Add(safeIntPtr); }