using System; using System.Collections.Generic; using System.Runtime.InteropServices; public abstract class CallbackHandler where THandler: CallbackHandler { private GCHandle selfHandle; private GCHandle callbacksHandle; public IntPtr ContextPtr => GCHandle.ToIntPtr(selfHandle); public IntPtr CallbacksPtr => callbacksHandle.AddrOfPinnedObject(); protected CallbackHandler() { selfHandle = GCHandle.Alloc(this); } public virtual void Destroy() { if (callbacksHandle.IsAllocated) callbacksHandle.Free(); selfHandle.Free(); } protected IntPtr CreateCallback(TDelegate callback) { return Marshal.GetFunctionPointerForDelegate(callback); } protected void RegisterCallbacks(TCallbacks callbacks) { // Pin the callbacks struct so that native code can safely keep a pointer to it and re-use it on subsequent calls callbacksHandle = GCHandle.Alloc(callbacks, GCHandleType.Pinned); } protected static THandler GetSelf(IntPtr target) { return (THandler)GCHandle.FromIntPtr(target).Target; } }