Skip to content

Commit

Permalink
feat: Export methods for levilamina plugin manager
Browse files Browse the repository at this point in the history
  • Loading branch information
Pd233 committed May 14, 2024
1 parent 2f70059 commit d591e9d
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/Hosihikari.PluginManager.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<EnableDynamicLoading>true</EnableDynamicLoading>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

</Project>
102 changes: 99 additions & 3 deletions src/Main.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using Hosihikari.PluginManager;
using System.Collections.Immutable;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;

namespace Hosihikari.PluginManagement;

internal static class Main
internal unsafe static class Main
{
[UnmanagedCallersOnly]
public static void Initialize()
Expand All @@ -27,8 +29,7 @@ public static void Initialize()

foreach (FileInfo file in directoryInfo.EnumerateFiles())
{
AssemblyPlugin plugin = new(file);
Manager.Load(plugin);
LoadPlugin(file);
}
}

Expand All @@ -47,4 +48,99 @@ public static void Initialize()
Environment.FailFast(default, ex);
}
}

public static AssemblyPlugin LoadPlugin(FileInfo file)
{
AssemblyPlugin plugin = new(file);
Manager.Load(plugin);
return plugin;
}

[UnmanagedCallersOnly]
public static unsafe nint LoadPluginUnmanaged(byte* pathStr, delegate* unmanaged[Stdcall]<byte*, void> errorHandler)
{
try
{
var path = Utf8StringMarshaller.ConvertToManaged(pathStr);
if (string.IsNullOrWhiteSpace(path))
throw new NullReferenceException("Path is null or whitespace.");
var file = new FileInfo(path);
var plugin = LoadPlugin(file);
var temp = new PluginHandle(plugin);
return temp.Handle;
}
catch (Exception ex)
{
var str = Utf8StringMarshaller.ConvertToUnmanaged(ex.Message);
errorHandler(str);
Utf8StringMarshaller.Free(str);
throw;
}
}

[UnmanagedCallersOnly]
public unsafe static void Load(void* handle, void* arg, delegate* unmanaged[Stdcall]<void*, /* bool */bool, /* char const* */byte*, void> fptr)
{
try
{
var target = GCHandle.FromIntPtr((nint)handle).Target as Plugin
?? throw new NullReferenceException("Plugin is null");
target.Load();
target.Initialize();

fptr(arg, true, null);
return;
}
catch (Exception ex)
{
var str = Utf8StringMarshaller.ConvertToUnmanaged(ex.ToString());
fptr(arg, false, str);
Utf8StringMarshaller.Free(str);
return;
}
}

[UnmanagedCallersOnly]
public unsafe static void Enable(void* handle, void* arg, delegate* unmanaged[Stdcall]<void*, /* bool */bool, /* char const* */byte*, void> fptr)
{
fptr(arg, true, null);
return;
}

[UnmanagedCallersOnly]
public unsafe static void Disable(void* handle, void* arg, delegate* unmanaged[Stdcall]<void*, /* bool */bool, /* char const* */byte*, void> fptr)
{
fptr(arg, true, null);
return;
}

[UnmanagedCallersOnly]
public unsafe static void Unload(void* handle, void* arg, delegate* unmanaged[Stdcall]<void*, /* bool */bool, /* char const* */byte*, void> fptr)
{
try
{
var target = GCHandle.FromIntPtr((nint)handle).Target as Plugin
?? throw new NullReferenceException("Plugin is null");
target.Unload();
fptr(arg, true, null);
return;
}
catch (Exception ex)
{
var str = Utf8StringMarshaller.ConvertToUnmanaged(ex.ToString());
fptr(arg, false, str);
Utf8StringMarshaller.Free(str);
return;
}
}

[UnmanagedCallersOnly]
public unsafe static void ReleaseHandle(void* handle, void* arg, delegate* unmanaged[Stdcall]<void*, /* bool */bool, /* char const* */byte*, void> fptr)
{
var gch = GCHandle.FromIntPtr((nint)handle);
if (gch.IsAllocated)
gch.Free();
fptr(arg, true, null);
return;
}
}
10 changes: 10 additions & 0 deletions src/PluginHandle.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Hosihikari.PluginManagement;
using System.Runtime.InteropServices;

namespace Hosihikari.PluginManager;

[StructLayout(LayoutKind.Sequential)]
public readonly unsafe struct PluginHandle(Plugin plugin)
{
public readonly nint Handle = GCHandle.ToIntPtr(GCHandle.Alloc(plugin));
}

0 comments on commit d591e9d

Please sign in to comment.