Skip to content

Commit

Permalink
Enable way to load interface without generic
Browse files Browse the repository at this point in the history
  • Loading branch information
ThadHouse committed Jan 18, 2020
1 parent f564f46 commit 0e3d75c
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/FRC-Utilities/FRC-Utilities.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
<PropertyGroup>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsAsErrors />
<Version>3.0.4</Version>
<Version>3.0.5</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
21 changes: 13 additions & 8 deletions src/FRC-Utilities/ILGeneration/InterfaceGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace FRC.ILGeneration
{
internal class InterfaceGenerator<T> where T : class
internal class InterfaceGenerator
{
private readonly IFunctionPointerLoader functionPointerLoader;
private readonly IILGenerator ilGenerator;
Expand All @@ -18,15 +18,20 @@ public InterfaceGenerator(IFunctionPointerLoader functionPointerLoader, IILGener
this.functionPointerLoader = functionPointerLoader;
this.ilGenerator = ilGenerator;
}

public T? GenerateImplementation<T>() 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)
{
Expand All @@ -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);
}
}
}
22 changes: 20 additions & 2 deletions src/FRC-Utilities/NativeLibraryUtilities/NativeLibraryLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -342,8 +342,26 @@ public void LoadNativeLibraryFromReflectedAssembly(string assemblyName, bool loc
}

var ilGenerator = new CalliILGenerator();
var interfaceGenerator = new InterfaceGenerator<T>(LibraryLoader, ilGenerator);
return interfaceGenerator.GenerateImplementation();
var interfaceGenerator = new InterfaceGenerator(LibraryLoader, ilGenerator);
return interfaceGenerator.GenerateImplementation<T>();
}

/// <summary>
/// Load a native interface
/// </summary>
/// <returns></returns>
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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ public void TestInterfaceGeneration1Func()
});

var ilGenerator = new CalliILGenerator();
InterfaceGenerator<I1Func> iGenerator = new InterfaceGenerator<I1Func>(fpLoader, ilGenerator);
var impl = iGenerator.GenerateImplementation();
InterfaceGenerator iGenerator = new InterfaceGenerator(fpLoader, ilGenerator);
var impl = iGenerator.GenerateImplementation<I1Func>();
Assert.NotNull(impl);
int x = 5;
byte r = impl!.FirstFunc(&x);
Expand Down

0 comments on commit 0e3d75c

Please sign in to comment.