Skip to content

Commit

Permalink
Add support for registering function pointers as event handlers. (#57)
Browse files Browse the repository at this point in the history
  • Loading branch information
jhett12321 authored Nov 23, 2023
1 parent 9f4a300 commit df246f7
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 5 deletions.
14 changes: 14 additions & 0 deletions src/Core/NWNCore.Native.Events.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Runtime.InteropServices;

namespace NWN.Core
Expand Down Expand Up @@ -26,5 +27,18 @@ public struct NativeEventHandles
public AssertHandlerDelegate AssertFail;
public CrashHandlerDelegate CrashHandler;
}

#if !NETCOREAPP3_1
[StructLayout(LayoutKind.Sequential)]
public unsafe struct NativeEventHandlesUnmanaged
{
public delegate* unmanaged<ulong, void> MainLoop;
public delegate* unmanaged<IntPtr, uint, int> RunScript;
public delegate* unmanaged<ulong, uint, void> Closure;
public delegate* unmanaged<IntPtr, void> Signal;
public delegate* unmanaged<IntPtr, IntPtr, void> AssertFail;
public delegate* unmanaged<int, IntPtr, void> CrashHandler;
}
#endif
}
}
30 changes: 25 additions & 5 deletions src/Core/NWNCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static partial class NWNCore
internal static NativeHandles NativeFunctions;

// We hold a reference to prevent GC of the delegates.
private static NativeEventHandles eventHandles;
private static object eventHandles;

Check warning on line 20 in src/Core/NWNCore.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable field 'eventHandles' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 20 in src/Core/NWNCore.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable field 'eventHandles' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

public static int Init(IntPtr nativeHandlesPtr, int nativeHandlesLength, ICoreFunctionHandler functionHandler, ICoreEventHandler eventHandler)
{
Expand All @@ -41,6 +41,19 @@ public static int Init(IntPtr nativeHandlesPtr, int nativeHandlesLength, ICoreFu
return result;
}

#if !NETCOREAPP3_1
public static int Init(IntPtr nativeHandlesPtr, int nativeHandlesLength, ICoreFunctionHandler functionHandler, NativeEventHandlesUnmanaged eventCallbackHandles)
{
int result = Init(nativeHandlesPtr, nativeHandlesLength, functionHandler);
if (result == 0)
{
RegisterEventHandles(eventCallbackHandles);
}

return result;
}
#endif

public static int Init(IntPtr nativeHandlesPtr, int nativeHandlesLength, ICoreFunctionHandler functionHandler)
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
Expand Down Expand Up @@ -89,18 +102,25 @@ public static void RegisterEventHandles(ICoreEventHandler eventHandler)
RegisterEventHandles(eventHandles);
}

public static void RegisterEventHandles(NativeEventHandles eventCallbackHandles)
public static void RegisterEventHandles<T>(T eventCallbackHandles) where T : struct
{
if (FunctionHandler == null)
{
throw new InvalidOperationException("Init must be called first with a valid function handler.");
}

int expectedSize = Marshal.SizeOf<NativeEventHandles>();
int actualSize = Marshal.SizeOf<T>();

if (actualSize != expectedSize)
{
throw new InvalidOperationException($"Invalid event handle structure specified. Expected size {expectedSize}, Actual size: {actualSize}");
}

eventHandles = eventCallbackHandles;
int size = Marshal.SizeOf(typeof(NativeEventHandles));
IntPtr ptr = Marshal.AllocHGlobal(size);
IntPtr ptr = Marshal.AllocHGlobal(actualSize);
Marshal.StructureToPtr(eventHandles, ptr, false);
NativeFunctions.RegisterHandlers(ptr, (uint)size);
NativeFunctions.RegisterHandlers(ptr, (uint)actualSize);
Marshal.FreeHGlobal(ptr);
}
}
Expand Down

0 comments on commit df246f7

Please sign in to comment.