using System; using System.Collections.Generic; using System.Linq; using Vanara.Extensions; using Vanara.InteropServices; namespace Vanara.PInvoke { /// /// Interface that identifies a structure containing only a 4-byte size field followed by a pointer to an array of . /// /// A marshalable structure. public interface IArrayStruct where T : struct { } /// Extension methods for . public static class IArrayStructExtensions { /// Gets the array from an instance. /// The type of the array. /// The instance. /// The array contained in the instance. public static T[] GetArray(this IArrayStruct ias) where T : struct { using var pin = new PinnedObject(ias); return ((IntPtr)pin).ToArray((int)((IntPtr)pin).ToStructure(), sizeof(uint)); } } /// Allows marshaling of arrays in place of a structure supporting . /// The type of the array element. /// public class IArrayStructMarshaler : IVanaraMarshaler where T : struct { public static readonly int hSz = sizeof(uint); /// public SizeT GetNativeSize() => hSz + IntPtr.Size; /// public SafeAllocatedMemoryHandle MarshalManagedToNative(object managedObject) { if (managedObject is IEnumerable ias) { var cnt = ias.Count(); var mem = new SafeHGlobalHandle(hSz + InteropExtensions.SizeOf() * cnt); mem.Write(cnt); mem.Write(ias, true, hSz); return mem; } throw new ArgumentException("Unexpected type. Value must be of IEnumerable."); } /// public object MarshalNativeToManaged(IntPtr pNativeData, SizeT allocatedBytes) { if (pNativeData == default) return new T[0]; var cnt = pNativeData.ToStructure(); return pNativeData.ToArray((int)cnt, hSz, allocatedBytes); } } }