Skip to content

Commit 04b1424

Browse files
author
dahall
committed
Added Array.MarshalToPtr extension method
1 parent 5591b5a commit 04b1424

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

Core/Extensions/InteropExtensions.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,33 @@ public static IntPtr MarshalToPtr<T>(this T value, Func<int, IntPtr> memAlloc, o
339339
}
340340
}
341341

342+
/// <summary>
343+
/// Marshals data from a managed list of specified type to an unmanaged block of memory allocated by the <paramref name="memAlloc"/> method.
344+
/// </summary>
345+
/// <param name="items">
346+
/// The array of items to marshal. If this is an array of strings, it will be marshaled as a concatenated list with default character encoding.
347+
/// </param>
348+
/// <param name="memAlloc">
349+
/// The function that allocates the memory for the block of items (typically <see cref="Marshal.AllocCoTaskMem(int)"/> or <see cref="Marshal.AllocHGlobal(int)"/>.
350+
/// </param>
351+
/// <param name="bytesAllocated">The bytes allocated by the <paramref name="memAlloc"/> method.</param>
352+
/// <param name="prefixBytes">Number of bytes preceding the trailing strings.</param>
353+
/// <param name="memLock">
354+
/// The function used to lock memory before assignment. If <see langword="null"/>, the result from <paramref name="memAlloc"/> will be used.
355+
/// </param>
356+
/// <param name="memUnlock">The optional function to unlock memory after assignment.</param>
357+
/// <returns>Pointer to the allocated native (unmanaged) array of items stored.</returns>
358+
/// <exception cref="ArgumentException">Structure layout is not sequential or explicit.</exception>
359+
public static IntPtr MarshalToPtr(this Array items, Func<int, IntPtr> memAlloc, out int bytesAllocated, SizeT prefixBytes = default, Func<IntPtr, IntPtr>? memLock = null, Func<IntPtr, bool>? memUnlock = null)
360+
{
361+
if (items.Rank != 1)
362+
throw new ArgumentException("Only single dimension arrays are supported.", nameof(items));
363+
if (items.GetType().GetElementType() == typeof(string))
364+
return items.Cast<string?>().MarshalToPtr(StringListPackMethod.Concatenated, memAlloc, out bytesAllocated, CharSet.Auto, prefixBytes, memLock, memUnlock);
365+
return (IntPtr)typeof(IEnumerable<>).MakeGenericType(items.GetType().GetElementType()!).GetMethod(nameof(MarshalToPtr), new[] { typeof(IEnumerable<>), typeof(Func<int, IntPtr>), typeof(int).MakeByRefType(), typeof(SizeT), typeof(Func<IntPtr, IntPtr>), typeof(Func<IntPtr, bool>) })!
366+
.MakeGenericMethod(items.GetType().GetElementType()!).Invoke(null, new object?[] { items, memAlloc, bytesAllocated = 0, prefixBytes, memLock, memUnlock }!)!;
367+
}
368+
342369
/// <summary>
343370
/// Marshals data from a managed list of specified type to an unmanaged block of memory allocated by the <paramref name="memAlloc"/> method.
344371
/// </summary>

0 commit comments

Comments
 (0)