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
{
/// The header size.
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);
}
}
}