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.Collections.Generic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using UnityEngine; using UnityEngine;
using UnityEngine.Events;
public class Uniquake: MonoBehaviour public class Uniquake: MonoBehaviour
{ {
@ -75,7 +74,7 @@ public class Uniquake: MonoBehaviour
} }
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] [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)] [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
private static extern void Uniquake_Init(IntPtr callbacks, QuakeParms parms); private static extern void Uniquake_Init(IntPtr callbacks, QuakeParms parms);
@ -83,19 +82,25 @@ public class Uniquake: MonoBehaviour
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
private static extern void Uniquake_Update(float deltaTime); 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) private static void Callback_DebugLog(string message)
{ {
Debug.Log(message); Debug.Log(message);
} }
[AOT.MonoPInvokeCallback(typeof(UnityCallbacks.DebugLogErrorCallback))]
private delegate void DebugLogErrorCallback([MarshalAs(UnmanagedType.LPStr)] string message);
[AOT.MonoPInvokeCallback(typeof(DebugLogErrorCallback))]
private static void Callback_DebugLogError(string message) private static void Callback_DebugLogError(string message)
{ {
Debug.LogError(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) private static void Callback_ApplicationQuit(int exitCode)
{ {
Debug.Log($"Quitting application with exit code: {exitCode}"); Debug.Log($"Quitting application with exit code: {exitCode}");
@ -103,26 +108,29 @@ public class Uniquake: MonoBehaviour
Application.Quit(exitCode); Application.Quit(exitCode);
} }
[AOT.MonoPInvokeCallback(typeof(UnityCallbacks.RealtimeSinceStartupCallback))]
private delegate double RealtimeSinceStartupCallback();
[AOT.MonoPInvokeCallback(typeof(RealtimeSinceStartupCallback))]
private static double Callback_RealtimeSinceStartup() private static double Callback_RealtimeSinceStartup()
{ {
return Time.realtimeSinceStartupAsDouble; return Time.realtimeSinceStartupAsDouble;
} }
private class UnityCallbacks private class UnityCallbacks
{ {
private List<GCHandle> handles = new List<GCHandle>();
private UnityCallbacksContainer container; private UnityCallbacksContainer container;
private GCHandle containerHandle; private GCHandle containerHandle;
public UnityCallbacks() 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); containerHandle = GCHandle.Alloc(container, GCHandleType.Pinned);
} }
@ -131,30 +139,21 @@ public class Uniquake: MonoBehaviour
public void Destroy() 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)] [StructLayout(LayoutKind.Sequential, Pack = 0)]

Loading…
Cancel
Save