static SafeHGlobalHandle AllocHGlobal(int cb) { if (cb < 0) { throw new ArgumentOutOfRangeException(nameof(cb), "The value of this argument must be non-negative"); } var result = new SafeHGlobalHandle(); // // CER // RuntimeHelpers.PrepareConstrainedRegions(); result._pointer = Marshal.AllocHGlobal(cb); return(result); }
/// <summary> /// Allocates from unmanaged memory to represent a structure with a /// variable length array at the end and marshal these structure /// elements. It is the callers responsibility to marshal what preceeds /// the trailinh array into the unmanaged memory. ONLY structures with /// attribute StructLayout of LayoutKind.Sequential are supported. /// </summary> /// <typeparam name="T">Type of the trailing array of structures</typeparam> /// <param name="prefixBytes">Number of bytes preceeding the trailing array of structures</param> /// <param name="values">Collection of structure objects</param> /// <param name="count"></param> /// <returns>SafeHGlobalHandle object to an native (unmanaged) structure /// with a trail array of structures</returns> public static SafeHGlobalHandle AllocHGlobal <T>(int prefixBytes, IEnumerable <T> values, int count) where T : struct { var structLayoutAttribute = typeof(T).StructLayoutAttribute; Debug.Assert(structLayoutAttribute != null && structLayoutAttribute.Value == LayoutKind.Sequential); SafeHGlobalHandle result = AllocHGlobal(prefixBytes + Marshal.SizeOf(typeof(T)) * count); IntPtr ptr = result._pointer + prefixBytes; foreach (var value in values) { Marshal.StructureToPtr(value, ptr, false); ptr += Marshal.SizeOf(typeof(T)); } return(result); }