diff --git a/src/FRC-Utilities/FRC-Utilities.csproj b/src/FRC-Utilities/FRC-Utilities.csproj index 459d75f..f7efa99 100644 --- a/src/FRC-Utilities/FRC-Utilities.csproj +++ b/src/FRC-Utilities/FRC-Utilities.csproj @@ -27,7 +27,7 @@ true - 3.0.4 + 3.0.5 diff --git a/src/FRC-Utilities/ILGeneration/InterfaceGenerator.cs b/src/FRC-Utilities/ILGeneration/InterfaceGenerator.cs index 07d36d1..0df4154 100644 --- a/src/FRC-Utilities/ILGeneration/InterfaceGenerator.cs +++ b/src/FRC-Utilities/ILGeneration/InterfaceGenerator.cs @@ -8,7 +8,7 @@ namespace FRC.ILGeneration { - internal class InterfaceGenerator where T : class + internal class InterfaceGenerator { private readonly IFunctionPointerLoader functionPointerLoader; private readonly IILGenerator ilGenerator; @@ -18,15 +18,20 @@ public InterfaceGenerator(IFunctionPointerLoader functionPointerLoader, IILGener this.functionPointerLoader = functionPointerLoader; this.ilGenerator = ilGenerator; } + + public T? GenerateImplementation() where T : class + { + return (T?)GenerateImplementation(typeof(T)); + } - public T? GenerateImplementation() + public object? GenerateImplementation(Type t) { - AssemblyBuilder asmBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(typeof(T).Name + "Asm"), AssemblyBuilderAccess.Run); - ModuleBuilder moduleBuilder = asmBuilder.DefineDynamicModule(typeof(T).Name + "Module"); - TypeBuilder typeBuilder = moduleBuilder.DefineType("Default" + typeof(T).Name); - typeBuilder.AddInterfaceImplementation(typeof(T)); + AssemblyBuilder asmBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(t.Name + "Asm"), AssemblyBuilderAccess.Run); + ModuleBuilder moduleBuilder = asmBuilder.DefineDynamicModule(t.Name + "Module"); + TypeBuilder typeBuilder = moduleBuilder.DefineType("Default" + t.Name); + typeBuilder.AddInterfaceImplementation(t); - var methods = typeof(T).GetMethods(BindingFlags.Public | BindingFlags.Instance); + var methods = t.GetMethods(BindingFlags.Public | BindingFlags.Instance); foreach (var method in methods) { @@ -43,7 +48,7 @@ public InterfaceGenerator(IFunctionPointerLoader functionPointerLoader, IILGener var typeInfo = typeBuilder.CreateTypeInfo(); - return (T?)typeInfo?.GetConstructor(new Type[0]).Invoke(null); + return typeInfo?.GetConstructor(new Type[0]).Invoke(null); } } } diff --git a/src/FRC-Utilities/NativeLibraryUtilities/NativeLibraryLoader.cs b/src/FRC-Utilities/NativeLibraryUtilities/NativeLibraryLoader.cs index 630de40..4777457 100644 --- a/src/FRC-Utilities/NativeLibraryUtilities/NativeLibraryLoader.cs +++ b/src/FRC-Utilities/NativeLibraryUtilities/NativeLibraryLoader.cs @@ -342,8 +342,26 @@ public void LoadNativeLibraryFromReflectedAssembly(string assemblyName, bool loc } var ilGenerator = new CalliILGenerator(); - var interfaceGenerator = new InterfaceGenerator(LibraryLoader, ilGenerator); - return interfaceGenerator.GenerateImplementation(); + var interfaceGenerator = new InterfaceGenerator(LibraryLoader, ilGenerator); + return interfaceGenerator.GenerateImplementation(); + } + + /// + /// Load a native interface + /// + /// + public object? LoadNativeInterface(Type t) { + if (!t.IsInterface) { + throw new InvalidOperationException($"{t.Name} must be an interface"); + } + + if (LibraryLoader == null) { + throw new InvalidOperationException("A native library is not already loaded"); + } + + var ilGenerator = new CalliILGenerator(); + var interfaceGenerator = new InterfaceGenerator(LibraryLoader, ilGenerator); + return interfaceGenerator.GenerateImplementation(t); } private void ExtractNativeLibrary(string resourceLocation, string extractLocation, Assembly asm) diff --git a/test/FRC-Utilities.Test/ILGeneration/InterfaceGeneratorTest.cs b/test/FRC-Utilities.Test/ILGeneration/InterfaceGeneratorTest.cs index 312f4c1..c382b6f 100644 --- a/test/FRC-Utilities.Test/ILGeneration/InterfaceGeneratorTest.cs +++ b/test/FRC-Utilities.Test/ILGeneration/InterfaceGeneratorTest.cs @@ -41,8 +41,8 @@ public void TestInterfaceGeneration1Func() }); var ilGenerator = new CalliILGenerator(); - InterfaceGenerator iGenerator = new InterfaceGenerator(fpLoader, ilGenerator); - var impl = iGenerator.GenerateImplementation(); + InterfaceGenerator iGenerator = new InterfaceGenerator(fpLoader, ilGenerator); + var impl = iGenerator.GenerateImplementation(); Assert.NotNull(impl); int x = 5; byte r = impl!.FirstFunc(&x);