using System; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Vanara.Extensions; namespace Vanara.PInvoke { /// Helper methods for structures. public static class StructHelper { /// Gets the address of a reference. /// The unmanaged value type to convert. /// The target value. /// The address of . /// This address will only remain valid if the target value or its encapsulating type are pinned. public static IntPtr DangerousAddressOf(ref T target) where T : unmanaged { unsafe { fixed (T* p = &target) return (IntPtr)p; } } /// Converts a field reference to array. Used when a structure defines an ANYSIZE array as the last field. /// The unmanaged type to convert. /// A reference to the field value. /// The number of items in the array. /// The offset from the field value at which to start extracting the array. /// An item array of values of . /// /// Properties defined with this can only be safely used when the structure has been marshaled via a dynamic memory block and not /// when marshaled directly. /// #if !(NET20 || NET35 || NET40) [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public unsafe static T[] FieldToArray(ref T fieldReference, int count, int offset = 0) where T : unmanaged { if (count == 0) return new T[0]; return DangerousAddressOf(ref fieldReference).ToArray(count, offset); } /// Creates a new instance of with a size field set to the size of its unmanaged type. /// The type to return . /// /// Name of the field which is assigned the size. If , the first public or private field is used. /// /// An initialized instance of . public static T InitWithSize(string fieldName = null) where T : new() { const BindingFlags bf = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; var fi = fieldName is null ? typeof(T).GetOrderedFields(bf).FirstOrDefault() : typeof(T).GetField(fieldName, bf); var ret = (object)new T(); fi.SetValue(ret, Convert.ChangeType((uint)InteropExtensions.SizeOf(), fi.FieldType)); return (T)ret; } } }