Browse Source

Further simplified mechanism for creating and pinning callbacks. We don't care about the individual GCHandles so just throw them into a list for easy management.

console
Nico de Poel 5 years ago
parent
commit
2ef1b24042
  1. 65
      Assets/Scripts/Uniquake.cs

65
Assets/Scripts/Uniquake.cs

@ -3,7 +3,6 @@ using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Events;
public class Uniquake: MonoBehaviour
{
@ -75,7 +74,7 @@ public class Uniquake: MonoBehaviour
}
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
private static extern void Uniquake_Echo(UnityCallbacks.DebugLogCallback logCallback, [MarshalAs(UnmanagedType.LPStr)] string message);
private static extern void Uniquake_Echo(DebugLogCallback logCallback, [MarshalAs(UnmanagedType.LPStr)] string message);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
private static extern void Uniquake_Init(IntPtr callbacks, QuakeParms parms);
@ -83,19 +82,25 @@ public class Uniquake: MonoBehaviour
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
private static extern void Uniquake_Update(float deltaTime);
[AOT.MonoPInvokeCallback(typeof(UnityCallbacks.DebugLogCallback))]
private delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)] string message);
[AOT.MonoPInvokeCallback(typeof(DebugLogCallback))]
private static void Callback_DebugLog(string message)
{
Debug.Log(message);
}
private delegate void DebugLogErrorCallback([MarshalAs(UnmanagedType.LPStr)] string message);
[AOT.MonoPInvokeCallback(typeof(UnityCallbacks.DebugLogErrorCallback))]
[AOT.MonoPInvokeCallback(typeof(DebugLogErrorCallback))]
private static void Callback_DebugLogError(string message)
{
Debug.LogError(message);
}
[AOT.MonoPInvokeCallback(typeof(UnityCallbacks.ApplicationQuitCallback))]
private delegate void ApplicationQuitCallback(int exitCode);
[AOT.MonoPInvokeCallback(typeof(ApplicationQuitCallback))]
private static void Callback_ApplicationQuit(int exitCode)
{
Debug.Log($"Quitting application with exit code: {exitCode}");
@ -103,26 +108,29 @@ public class Uniquake: MonoBehaviour
Application.Quit(exitCode);
}
[AOT.MonoPInvokeCallback(typeof(UnityCallbacks.RealtimeSinceStartupCallback))]
private delegate double RealtimeSinceStartupCallback();
[AOT.MonoPInvokeCallback(typeof(RealtimeSinceStartupCallback))]
private static double Callback_RealtimeSinceStartup()
{
return Time.realtimeSinceStartupAsDouble;
}
private class UnityCallbacks
{
private List<GCHandle> handles = new List<GCHandle>();
private UnityCallbacksContainer container;
private GCHandle containerHandle;
public UnityCallbacks()
{
container = new UnityCallbacksContainer();
CreateCallback<DebugLogCallback>(Callback_DebugLog, out DebugLogHandle, out container.DebugLogPtr);
CreateCallback<DebugLogErrorCallback>(Callback_DebugLogError, out DebugLogErrorHandle, out container.DebugLogErrorPtr);
CreateCallback<ApplicationQuitCallback>(Callback_ApplicationQuit, out ApplicationQuitHandle, out container.ApplicationQuitPtr);
CreateCallback<RealtimeSinceStartupCallback>(Callback_RealtimeSinceStartup, out RealtimeSinceStartupHandle, out container.RealtimeSinceStartupPtr);
container = new UnityCallbacksContainer
{
DebugLogPtr = CreateCallback<DebugLogCallback>(Callback_DebugLog),
DebugLogErrorPtr = CreateCallback<DebugLogErrorCallback>(Callback_DebugLogError),
ApplicationQuitPtr = CreateCallback<ApplicationQuitCallback>(Callback_ApplicationQuit),
RealtimeSinceStartupPtr = CreateCallback<RealtimeSinceStartupCallback>(Callback_RealtimeSinceStartup),
};
containerHandle = GCHandle.Alloc(container, GCHandleType.Pinned);
}
@ -131,30 +139,21 @@ public class Uniquake: MonoBehaviour
public void Destroy()
{
containerHandle.Free();
DebugLogHandle.Free();
DebugLogErrorHandle.Free();
ApplicationQuitHandle.Free();
RealtimeSinceStartupHandle.Free();
if (containerHandle.IsAllocated)
containerHandle.Free();
foreach (var handle in handles)
{
if (handle.IsAllocated)
handle.Free();
}
}
private static void CreateCallback<TDelegate>(TDelegate callback, out GCHandle handle, out IntPtr ptr)
private IntPtr CreateCallback<TDelegate>(TDelegate callback)
{
handle = GCHandle.Alloc(callback);
ptr = Marshal.GetFunctionPointerForDelegate(callback);
handles.Add(GCHandle.Alloc(callback));
return Marshal.GetFunctionPointerForDelegate(callback);
}
public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)] string message);
private GCHandle DebugLogHandle;
public delegate void DebugLogErrorCallback([MarshalAs(UnmanagedType.LPStr)] string message);
private GCHandle DebugLogErrorHandle;
public delegate void ApplicationQuitCallback(int exitCode);
private GCHandle ApplicationQuitHandle;
public delegate double RealtimeSinceStartupCallback();
private GCHandle RealtimeSinceStartupHandle;
}
[StructLayout(LayoutKind.Sequential, Pack = 0)]

Loading…
Cancel
Save