Browse Source

Reorganized callbacks so that the function pointers and the containing class are all pinned, which makes them safe to store inside the DLL and reuse them on subsequent update calls.

console
Nico de Poel 5 years ago
parent
commit
38840fa7c3
  1. 61
      Assets/Scripts/Uniquake.cs

61
Assets/Scripts/Uniquake.cs

@ -11,8 +11,8 @@ public class Uniquake: MonoBehaviour
private const int MemSize = 0x4000000; // 64 MB of heap space private const int MemSize = 0x4000000; // 64 MB of heap space
private const int MaxArgs = 50; // Corresponds with MAX_NUM_ARGVS in engine private const int MaxArgs = 50; // Corresponds with MAX_NUM_ARGVS in engine
private UnityCallbacks callbacks = new UnityCallbacks();
private QuakeParms quakeParms; private QuakeParms quakeParms;
private UnityCallbacks callbacks = new UnityCallbacks();
void Start() void Start()
{ {
@ -32,7 +32,7 @@ public class Uniquake: MonoBehaviour
quakeParms = new QuakeParms quakeParms = new QuakeParms
{ {
baseDir = Application.dataPath,
baseDir = Application.persistentDataPath,
cacheDir = null, cacheDir = null,
argc = arguments.Length, argc = arguments.Length,
argv = argv, argv = argv,
@ -40,7 +40,7 @@ public class Uniquake: MonoBehaviour
memSize = MemSize, memSize = MemSize,
}; };
Uniquake_Init(callbacks, quakeParms);
Uniquake_Init(callbacks.CallbacksPtr, quakeParms);
} }
void Update() void Update()
@ -50,6 +50,8 @@ public class Uniquake: MonoBehaviour
private void OnDestroy() private void OnDestroy()
{ {
callbacks.Destroy();
if (quakeParms != null) if (quakeParms != null)
{ {
if (quakeParms.memBase != IntPtr.Zero) if (quakeParms.memBase != IntPtr.Zero)
@ -76,7 +78,7 @@ public class Uniquake: MonoBehaviour
private static extern void Uniquake_Echo(UnityCallbacks.DebugLogCallback logCallback, [MarshalAs(UnmanagedType.LPStr)] string message); private static extern void Uniquake_Echo(UnityCallbacks.DebugLogCallback logCallback, [MarshalAs(UnmanagedType.LPStr)] string message);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
private static extern void Uniquake_Init(UnityCallbacks callbacks, QuakeParms parms);
private static extern void Uniquake_Init(IntPtr callbacks, QuakeParms parms);
[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);
@ -107,20 +109,61 @@ public class Uniquake: MonoBehaviour
return Time.realtimeSinceStartupAsDouble; return Time.realtimeSinceStartupAsDouble;
} }
[StructLayout(LayoutKind.Sequential, Pack = 0)]
private class UnityCallbacks private class UnityCallbacks
{ {
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);
containerHandle = GCHandle.Alloc(container, GCHandleType.Pinned);
}
public IntPtr CallbacksPtr => containerHandle.AddrOfPinnedObject();
public void Destroy()
{
containerHandle.Free();
DebugLogHandle.Free();
DebugLogErrorHandle.Free();
ApplicationQuitHandle.Free();
RealtimeSinceStartupHandle.Free();
}
private static void CreateCallback<TDelegate>(TDelegate callback, out GCHandle handle, out IntPtr ptr)
{
handle = GCHandle.Alloc(callback);
ptr = Marshal.GetFunctionPointerForDelegate(callback);
}
public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)] string message); public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)] string message);
public DebugLogCallback DebugLog = Callback_DebugLog;
private GCHandle DebugLogHandle;
public delegate void DebugLogErrorCallback([MarshalAs(UnmanagedType.LPStr)] string message); public delegate void DebugLogErrorCallback([MarshalAs(UnmanagedType.LPStr)] string message);
public DebugLogErrorCallback DebugLogError = Callback_DebugLogError;
private GCHandle DebugLogErrorHandle;
public delegate void ApplicationQuitCallback(int exitCode); public delegate void ApplicationQuitCallback(int exitCode);
public ApplicationQuitCallback ApplicationQuit = Callback_ApplicationQuit;
private GCHandle ApplicationQuitHandle;
public delegate double RealtimeSinceStartupCallback(); public delegate double RealtimeSinceStartupCallback();
public RealtimeSinceStartupCallback RealtimeSinceStartup = Callback_RealtimeSinceStartup;
private GCHandle RealtimeSinceStartupHandle;
}
[StructLayout(LayoutKind.Sequential, Pack = 0)]
private class UnityCallbacksContainer
{
public IntPtr DebugLogPtr;
public IntPtr DebugLogErrorPtr;
public IntPtr ApplicationQuitPtr;
public IntPtr RealtimeSinceStartupPtr;
} }
[StructLayout(LayoutKind.Sequential, Pack = 0)] [StructLayout(LayoutKind.Sequential, Pack = 0)]

Loading…
Cancel
Save