Merged projects with plugins and modules
This commit is contained in:
13
Plugins/CppWrapper/CppWrapper.csproj
Normal file
13
Plugins/CppWrapper/CppWrapper.csproj
Normal file
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\DiscordBotCore\DiscordBotCore.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
112
Plugins/CppWrapper/LibraryManagement/ExternLibrary.cs
Normal file
112
Plugins/CppWrapper/LibraryManagement/ExternLibrary.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using DiscordBotCore;
|
||||
|
||||
namespace CppWrapper.LibraryManagement
|
||||
{
|
||||
public sealed class ExternLibrary
|
||||
{
|
||||
public string LibraryPath { get; init; }
|
||||
public IntPtr LibraryHandle { get; private set; }
|
||||
|
||||
public ExternLibrary(string libraryPath)
|
||||
{
|
||||
LibraryPath = libraryPath;
|
||||
LibraryHandle = IntPtr.Zero;
|
||||
}
|
||||
|
||||
public void InitializeLibrary()
|
||||
{
|
||||
if(LibraryHandle != IntPtr.Zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Application.CurrentApplication.Logger.Log($"Loading library {LibraryPath}");
|
||||
|
||||
|
||||
if(!NativeLibrary.TryLoad(LibraryPath, out IntPtr hModule))
|
||||
{
|
||||
throw new DllNotFoundException($"Unable to load library {LibraryPath}");
|
||||
}
|
||||
|
||||
Application.CurrentApplication.Logger.Log($"Library {LibraryPath} loaded successfully [{hModule}]");
|
||||
|
||||
LibraryHandle = hModule;
|
||||
}
|
||||
|
||||
public void FreeLibrary()
|
||||
{
|
||||
if(LibraryHandle == IntPtr.Zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NativeLibrary.Free(LibraryHandle);
|
||||
LibraryHandle = IntPtr.Zero;
|
||||
|
||||
Application.CurrentApplication.Logger.Log($"Library {LibraryPath} freed successfully");
|
||||
}
|
||||
|
||||
private IntPtr GetFunctionPointer(string functionName)
|
||||
{
|
||||
if(LibraryHandle == IntPtr.Zero)
|
||||
{
|
||||
throw new InvalidOperationException("Library is not loaded");
|
||||
}
|
||||
|
||||
if(!NativeLibrary.TryGetExport(LibraryHandle, functionName, out IntPtr functionPointer))
|
||||
{
|
||||
throw new EntryPointNotFoundException($"Unable to find function {functionName}");
|
||||
}
|
||||
|
||||
return functionPointer;
|
||||
}
|
||||
|
||||
public T GetDelegateForFunctionPointer<T>(string methodName) where T : Delegate
|
||||
{
|
||||
IntPtr functionPointer = GetFunctionPointer(methodName);
|
||||
|
||||
Application.CurrentApplication.Logger.Log($"Function pointer for {methodName} obtained successfully [address: {functionPointer}]");
|
||||
|
||||
T result = (T)Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(T));
|
||||
|
||||
Application.CurrentApplication.Logger.Log($"Delegate for {methodName} created successfully");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private IntPtr GetFunctionPointerForDelegate<T>(T functionDelegate) where T : Delegate
|
||||
{
|
||||
IntPtr functionPointer = Marshal.GetFunctionPointerForDelegate(functionDelegate);
|
||||
|
||||
Application.CurrentApplication.Logger.Log($"Function pointer for delegate {functionDelegate.Method.Name} obtained successfully [address: {functionPointer}]");
|
||||
|
||||
return functionPointer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tells the extern setter function to point its function to this C# function instead.
|
||||
/// This function takes the name of the extern setter function and the C# function to be executed.
|
||||
/// <para><b>How it works:</b></para>
|
||||
/// Find the external setter method by its name. It should take one parameter, which is the pointer to the function to be executed.
|
||||
/// Take the delegate function that should be executed and get its function pointer.
|
||||
/// Call the external setter with the new function memory address. This should replace the old C++ function with the new C# function.
|
||||
/// </summary>
|
||||
/// <param name="setterExternFunctionName">The setter function name</param>
|
||||
/// <param name="executableFunction">The function that the C++ setter will make its internal function to point to</param>
|
||||
/// <typeparam name="ExecuteDelegate">A delegate that reflects the executable function structure</typeparam>
|
||||
/// <typeparam name="SetDelegate">The Setter delegate </typeparam>
|
||||
/// <returns>A response if it exists as an object</returns>
|
||||
public object? SetExternFunctionSetterPointerToCustomDelegate<SetDelegate, ExecuteDelegate>(string setterExternFunctionName, ExecuteDelegate executableFunction) where ExecuteDelegate : Delegate where SetDelegate : Delegate
|
||||
{
|
||||
SetDelegate setterDelegate = GetDelegateForFunctionPointer<SetDelegate>(setterExternFunctionName);
|
||||
IntPtr executableFunctionPtr = GetFunctionPointerForDelegate(executableFunction);
|
||||
|
||||
var result = setterDelegate.DynamicInvoke(executableFunctionPtr);
|
||||
|
||||
Application.CurrentApplication.Logger.Log($"Function {setterExternFunctionName} bound to local action successfully");
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Plugins/CppWrapper/Objects/ApplicationStruct.cs
Normal file
34
Plugins/CppWrapper/Objects/ApplicationStruct.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace CppWrapper.Objects
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||
public struct ApplicationStruct
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 19)]
|
||||
public string ServerId;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)]
|
||||
public string Prefix;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 71)]
|
||||
public string Token;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||
public struct ComplexObject
|
||||
{
|
||||
public int Integer;
|
||||
public double DoubleValue;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public string strValue;
|
||||
|
||||
public ComplexObject(int integer, double doubleValue, string strValue)
|
||||
{
|
||||
Integer = integer;
|
||||
DoubleValue = doubleValue;
|
||||
this.strValue = strValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
17
Plugins/CppWrapper/Objects/ObjectConvertor.cs
Normal file
17
Plugins/CppWrapper/Objects/ObjectConvertor.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using DiscordBotCore;
|
||||
|
||||
namespace CppWrapper.Objects
|
||||
{
|
||||
public static class ObjectConvertor
|
||||
{
|
||||
public static ApplicationStruct ToApplicationStruct(this Application application)
|
||||
{
|
||||
return new ApplicationStruct
|
||||
{
|
||||
Token = application.ApplicationEnvironmentVariables["token"],
|
||||
Prefix = application.ApplicationEnvironmentVariables["prefix"],
|
||||
ServerId = application.ServerID
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user