Skip to content

NetCore 2.2.3 Support #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Aug 19, 2019
Merged

NetCore 2.2.3 Support #12

merged 8 commits into from
Aug 19, 2019

Conversation

viferga
Copy link
Member

@viferga viferga commented May 30, 2019

I have tried to do the migration from NetCore 1.1 to 2.2.3 but it failed. It seems there is a problem with System.Runtime.Loader library.

Error:

System.TypeLoadException: Could not load type 'System.Runtime.Loader.AssemblyLoadContext'

It seems to fail at line 91 in CSLoader.cs when running any test containing the cs_loader.

When trying to find the error, with some experiments, it shown an error code like 0x80070002 (similar to this tjanczuk/edge#599) when calling to coreclr_create_delegate.
After searching it, it was FileNotFoundException (Exception from HRESULT: 0x80070002 (COR_E_FILENOTFOUND)). After updating manually the project.csproj it disapeared. When doing some research I found this:

https://github.com/dotnet/corefx/issues/22142#issuecomment-473392197

So now I am not sure if it fails because it is not found, or because csproj is not correctly defined with a valid NET Framework.
At least, NetCore documentation explains that it is truly supported, so the error may be a misconfiguration of csproj or NetCore cannot find the library System.Runtime.Loader.

Documentation:
https://github.com/dotnet/coreclr/blob/v2.1.0/Documentation/design-docs/assemblyloadcontext.md

Some updated examples for embedding netcore:
https://github.com/dotnet/coreclr/blob/master/src/coreclr/hosts/corerun/corerun.cpp
https://github.com/aspnet/dnx/blob/85f82f9dd6417eedc030e39ac72a182a0f7fba52/src/dnx.coreclr.unix/dnx.coreclr.cpp

@viferga
Copy link
Member Author

viferga commented Aug 14, 2019

I have been trying some changes but I did not test them yet.

https://github.com/richlander/dotnet-core-assembly-loading
https://www.strathweb.com/2019/01/collectible-assemblies-in-net-core-3-0/
https://stackoverflow.com/questions/51246097/load-assembly-in-startup-cs-net-core-2-1 // This one loads also the dependencies

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis;
using System.IO;
using Microsoft.CodeAnalysis.Emit;
using System.Runtime.Loader;
using System.Runtime.InteropServices;
using static CSLoader.MetacallDef;
using System.Collections.Immutable;

namespace CSLoader
{
   public class Loader
   {

       public static void Main(string[] args)
       {

       }

       private static Loader loader = null;

       static Loader()
       {
           #if NETCOREAPP1_0 || NETCOREAPP1_1
               AssemblyLoadContext.Default.Resolving += Context_Resolving;
           #endif

           Init();
       }
       
       public static void Init()
       {
           loader = new Loader();
       }

       public unsafe static bool LoadFromPointer(string[] source)
       {
           if (loader == null)
           {
               loader = new Loader();
           }

           return loader.LoadFromSourceFunctions(source);
       }

       public static bool Load(string source)
       {
           if (loader == null)
           {
               loader = new Loader();
           }

           return loader.LoadFromSourceFunctions(new string[] { source });
       }

       public static bool Load(string[] files)
       {
           if (loader == null)
           {
               loader = new Loader();
           }

           return loader.LoadFromSourceFunctions(files.Select(x => System.IO.File.ReadAllText(x)).ToArray());
       }

       public ReflectFunction[] Functions()
       {
           return this.functions.Select(x => x.Value.GetReflectFunction()).ToArray();
       }

       public static ReflectFunction[] GetFunctionsInternal()
       {
           return loader.Functions();
       }

       public static void GetFunctions(ref int count, IntPtr p)
       {
           var f = loader.Functions();
           count = f.Length;

           foreach (var item in f)
           {
               Marshal.StructureToPtr(item, p, false);
               p += Marshal.SizeOf<ReflectFunction>();
           }
       }

       public unsafe static bool LoadFilesC([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]IntPtr[] source, long size)
       {
           return Load(source.Select(x => Marshal.PtrToStringAnsi(x)).ToArray());
       }

       public unsafe static bool LoadFilesW([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]IntPtr[] source, long size)
       {
           return Load(source.Select(x => Marshal.PtrToStringUni(x)).ToArray());
       }

       public static bool LoadAssemblyC([MarshalAs(UnmanagedType.LPStr)]string assemblyFile)
       {
           return LoadFromAssembly(assemblyFile);
       }

       public static bool LoadAssemblyW([MarshalAs(UnmanagedType.LPWStr)]string assemblyFile)
       {
           return LoadFromAssembly(assemblyFile);
       }

       public static bool LoadSourceC([MarshalAs(UnmanagedType.LPStr)]string source)
       {
           return Load(source);
       }

       public static bool LoadSourceW([MarshalAs(UnmanagedType.LPWStr)]string source)
       {
           return Load(source);
       }

       public unsafe static IntPtr ExecuteC([System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)] string function)
       {
           return ExecuteFunction(function);
       }

       public unsafe static IntPtr ExecuteW([System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)] string function)
       {
           return ExecuteFunction(function);
       }

       public unsafe static void DestroyExecutionResult(ExecutionResult* executionResult)
       {
           if (executionResult->ptr != IntPtr.Zero)
           {
               Marshal.FreeHGlobal(executionResult->ptr);
           }

           Marshal.FreeHGlobal((IntPtr)executionResult);
       }

       public unsafe static IntPtr ExecuteWithParamsC([System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)] string function,
        [MarshalAs(UnmanagedType.LPArray, SizeConst = 10)]   Parameters[] parameters)
       {
           if (loader == null)
           {
               return (IntPtr)CreateExecutionResult(true, type_primitive_id.TYPE_PTR);
           }
           else
           {
               return (IntPtr)loader.Execute(function, parameters);
           }
       }

       public unsafe static IntPtr ExecuteWithParamsW([System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)] string function,
        [MarshalAs(UnmanagedType.LPArray, SizeConst = 10)]   Parameters[] parameters)
       {
           if (loader == null)
           {
               return (IntPtr)CreateExecutionResult(true, type_primitive_id.TYPE_PTR);
           }
           else
           {
               return (IntPtr)loader.Execute(function, parameters);
           }
       }

       public unsafe static IntPtr ExecuteFunction(string function)
       {
           if (loader == null)
           {
               return (IntPtr)CreateExecutionResult(true, type_primitive_id.TYPE_PTR);
           }
           else
           {
               return (IntPtr)loader.Execute(function);
           }
       }

       private Dictionary<string, FunctionContainer> functions = new Dictionary<string, FunctionContainer>();

       public Loader()
       {
       }

       public bool LoadFromSourceFunctions(string[] source)
       {
           Assembly assembly = null;

           SyntaxTree[] syntaxTrees = source.Select(x => CSharpSyntaxTree.ParseText(x)).ToArray();

           string assemblyName = Path.GetRandomFileName();

           MetadataReference[] references = new MetadataReference[]
           {
               MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location),
               MetadataReference.CreateFromFile(typeof(Enumerable).GetTypeInfo().Assembly.Location)
           };

           CSharpCompilation compilation = CSharpCompilation.Create(
               assemblyName,
               syntaxTrees: syntaxTrees,
               references: references,
               options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

           using (var ms = new MemoryStream())
           {
               EmitResult result = compilation.Emit(ms);

               if (!result.Success)
               {
                   IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>

                       diagnostic.Severity == DiagnosticSeverity.Error);

                   foreach (Diagnostic diagnostic in failures)
                   {
                       Console.Error.WriteLine("{0}: {1}", diagnostic.Id, diagnostic.GetMessage());
                   }
               }
               else
               {
                   ms.Seek(0, SeekOrigin.Begin);

                   #if NETCOREAPP1_0 || NETCOREAPP1_1
                       AssemblyLoadContext context = AssemblyLoadContext.Default;
                       assembly = context.LoadFromStream(ms);
                   #elif NETCOREAPP2_0 || NETCOREAPP2_1 || NETCOREAPP2_2
                       // TODO
                   #endif
               }
           }

           if (assembly != null)
           {
               this.LoadFunctions(assembly);
               return true;
           }
           else
           {
               return false;
           }
       }

       protected static List<string> paths = new List<string>();

       public static bool LoadFromAssembly(string assemblyFile)
       {
           Assembly asm = null;

           string path = System.IO.Path.GetDirectoryName(assemblyFile);

           if (!paths.Contains(path))
           {
               paths.Add(path);
           }

           #if NETCOREAPP1_0 || NETCOREAPP1_1
               AssemblyLoadContext context = AssemblyLoadContext.Default;

               try
               {
                   asm = context.LoadFromAssemblyPath(assemblyFile);
               }
               catch (Exception)
               {
               }

               if (asm == null)
               {
                   try
                   {
                       asm = context.LoadFromAssemblyName(new AssemblyName(System.IO.Path.GetFileNameWithoutExtension(assemblyFile)));
                   }
                   catch (Exception)
                   {
                   }
               }
           #elif NETCOREAPP2_0 || NETCOREAPP2_1 || NETCOREAPP2_2
               try
               {
                   string assemblyName = AssemblyLoadContext.GetAssemblyName(assemblyFile);
                   asm = Assembly.Load(assemblyName);
               }
               catch (Exception)
               {
               }
           #endif

           if (asm != null)
           {
               if (loader == null)
               {
                   loader = new Loader();
               }

               loader.LoadFunctions(asm);
               return true;
           }

           return false;
       }

       #if NETCOREAPP1_0 || NETCOREAPP1_1
           private static Assembly Context_Resolving(AssemblyLoadContext context, AssemblyName name)
           {
               Assembly asm = null;

               foreach (var path in paths)
               {
                   try
                   {
                       asm = context.LoadFromAssemblyPath(path + "\\" + name.Name + ".dll");

                       if (asm != null)
                       {
                           return asm;
                       }
                   }
                   catch (Exception ex)
                   {
                       Console.Error.WriteLine(ex.Message);
                   }
               }

               return asm;
           }
       #endif

       public static bool LoadFromAssemblyC([System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)] string assemblyFile)
       {
           return LoadFromAssembly(assemblyFile);
       }

       public static bool LoadFromAssemblyW([System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)] string assemblyFile)
       {
           return LoadFromAssembly(assemblyFile);
       }

       public void LoadFunctions(Assembly assembly)
       {
           foreach (var item in assembly.DefinedTypes.SelectMany(x => x.GetMethods()).Where(x => x.IsStatic))
           {
               var con = new FunctionContainer(item);

               if (!this.functions.ContainsKey(item.Name))
               {
                   this.functions.Add(item.Name, con);
               }
               else
               {
                   this.functions[item.Name] = con;
               }
           }

           GC.Collect();
       }

       public unsafe ExecutionResult* Execute(string function, Parameters[] parameters)
       {
           var objs = new object[parameters.Length];

           var con = this.functions[function];

           for (int i = 0; i < con.Parameters.Length; i++)
           {
               objs[i] = MetacallDef.GetValue(parameters[i].type, parameters[i].ptr);
           }

           var result = con.Method.Invoke(null, objs.Take(con.Parameters.Length).ToArray());

           if (result == null)
           {
               return CreateExecutionResult(false, MetacallDef.Get(con.RetunType));
           }
           else
           {
               return CreateExecutionResult(false, MetacallDef.Get(con.RetunType), result);
           }
       }

       public unsafe ExecutionResult* Execute(string function)
       {
           var con = this.functions[function];
           try
           {
               var result = con.Method.Invoke(null, null);

               if (result == null)
               {
                   return CreateExecutionResult(false, MetacallDef.Get(con.RetunType));
               }
               else
               {
                   return CreateExecutionResult(false, MetacallDef.Get(con.RetunType), result);
               }
           }
           catch (Exception ex)
           {
               Console.Error.WriteLine(ex.Message);
           }

           return null;
       }

       public unsafe static ExecutionResult* CreateExecutionResult(bool failed, type_primitive_id type)
       {
           ExecutionResult* er = (ExecutionResult*)Marshal.AllocHGlobal(sizeof(ExecutionResult));
           er->failed = failed;
           er->type = type;
           er->ptr = IntPtr.Zero;
           return er;
       }

       public unsafe static ExecutionResult* CreateExecutionResult(bool failed, type_primitive_id type, object value)
       {
           ExecutionResult* er = CreateExecutionResult(failed, type);

           er->ptr = MetacallDef.GetIntPtr(type, value);

           return er;
       }
   }
}

@viferga viferga merged commit 856f3ce into develop Aug 19, 2019
@viferga viferga deleted the feature/netcore2 branch July 22, 2021 16:27
RohanKrMahato pushed a commit to RohanKrMahato/core that referenced this pull request Dec 9, 2024
* [FEATURE] Added installation via Tarball Path

* Update install.ps1

Co-authored-by: Vicente Eduardo Ferrer Garcia <7854099+viferga@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants