// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) // // Copyright (c) 2022 JP Bruyère using System; using System.Linq; using System.Runtime.InteropServices; namespace Vulkan { /// /// Helper class to construct pnext chain /// public class PNext : IDisposable where T : struct { IntPtr handle; /// /// Allocate on HGlobal a new structure of type T, ensure instance is Disposed. /// public PNext () { init(); } /// /// Allocate on HGlobal a new structure of type T and set the pNext field, /// ensure instance is Disposed. /// public PNext (IntPtr pNext) { init(); Marshal.WriteIntPtr(handle + 4, pNext); } /// /// Allocate on HGlobal a new structure of type T and set current value /// ensure instance is Disposed. /// public PNext (T instance) { handle = Marshal.AllocHGlobal(Marshal.SizeOf()); Marshal.StructureToPtr(instance, handle, false); } /// /// Allocate on HGlobal a new structure of type T set current value and /// the PNext field. /// ensure instance is Disposed. /// public PNext (T instance, IntPtr pNext) { handle = Marshal.AllocHGlobal(Marshal.SizeOf()); Marshal.StructureToPtr(instance, handle, false); Marshal.WriteIntPtr(handle + 4, pNext); } void init() { handle = Marshal.AllocHGlobal(Marshal.SizeOf()); Type t = typeof(T); StructureTypeAttribute st = (StructureTypeAttribute)t.GetCustomAttributes(typeof(StructureTypeAttribute), false).FirstOrDefault(); Marshal.WriteInt32(handle, st.StructureType); } /// /// Get value of T /// public T Val => Marshal.PtrToStructure (handle); public static implicit operator IntPtr(PNext pn) => pn.handle; public void Dispose() { Marshal.FreeHGlobal(handle); } } }