using System; using System.Collections.Generic; using System.Runtime.InteropServices; public abstract class CallbackHandler where THandler: CallbackHandler { private GCHandle selfHandle; private GCHandle callbacksHandle; private List delegateHandles = new List(); public IntPtr ToIntPtr => callbacksHandle.AddrOfPinnedObject(); protected IntPtr SelfPtr => GCHandle.ToIntPtr(selfHandle); protected CallbackHandler() { selfHandle = GCHandle.Alloc(this); } public void Destroy() { if (callbacksHandle.IsAllocated) callbacksHandle.Free(); foreach (var handle in delegateHandles) { if (handle.IsAllocated) handle.Free(); } selfHandle.Free(); } protected IntPtr CreateCallback(TDelegate callback) { delegateHandles.Add(GCHandle.Alloc(callback)); return Marshal.GetFunctionPointerForDelegate(callback); } protected void RegisterCallbacks(TCallbacks callbacks) { callbacksHandle = GCHandle.Alloc(callbacks, GCHandleType.Pinned); } protected static THandler GetSelf(IntPtr target) { return (THandler)GCHandle.FromIntPtr(target).Target; } }