public static unsafe IntPtr CreateShim(ICallbackHandler handler) { if (handler == null) { return(IntPtr.Zero); } if (savedDelegates != null) { throw new InvalidOperationException("Callbacks should only be initialized once; bgfx can only deal with one set at a time."); } var memory = Marshal.AllocHGlobal(Marshal.SizeOf <CallbackShim>()); var shim = (CallbackShim *)memory; var saver = new DelegateSaver(handler, shim); // the shim uses the unnecessary ctor slot to act as a vtbl pointer to itself, // so that the same block of memory can act as both bgfx_callback_interface_t and bgfx_callback_vtbl_t shim->vtbl = memory + IntPtr.Size; // cache the data so we can free it later shimMemory = memory; savedDelegates = saver; return(memory); }
public static void FreeShim() { if (savedDelegates == null) return; savedDelegates = null; Marshal.FreeHGlobal(shimMemory); }
public static unsafe IntPtr CreateShim(ICallbackHandler handler) { if (handler == null) return IntPtr.Zero; if (savedDelegates != null) throw new InvalidOperationException("Callbacks should only be initialized once; bgfx can only deal with one set at a time."); var memory = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CallbackShim))); var shim = (CallbackShim*)memory; var saver = new DelegateSaver(handler, shim); // the shim uses the unnecessary ctor slot to act as a vtbl pointer to itself, // so that the same block of memory can act as both bgfx_callback_interface_t and bgfx_callback_vtbl_t shim->vtbl = memory + IntPtr.Size; // cache the data so we can free it later shimMemory = memory; savedDelegates = saver; return memory; }