Я пишу конкатенативный язык в C#, и в настоящее время он интерпретируется, но я хочу сделать следующий шаг: компиляция. Для начала я попытался написать простой «Hello, World!». программа, использующая System.Reflection.Emit. Код работает без каких-либо исключений испускают, но когда я запускаю созданный файл «test.exe», он бросает исключениеReflection.Emit: AssemblyBuilder.SetEntryPoint не устанавливает точку входа
Unhandled Exception: System.MissingMethodException: Entry point not found in assembly 'IL_Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
я пытался прибегая к помощи для ответа, но безрезультатно. Может, кто-то здесь может мне помочь? (Пожалуйста) код, который я написал ниже:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Reflection.Emit;
using System.IO;
using System.Diagnostics;
namespace ILCompileTest
{
class Program
{
static void Main(string[] args)
{
const string ASSEMBLY_NAME = "IL_Test";
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName(ASSEMBLY_NAME), AssemblyBuilderAccess.Save);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(
ASSEMBLY_NAME);
TypeBuilder typeBuilder = moduleBuilder.DefineType("Program",
TypeAttributes.Class | TypeAttributes.Public);
MethodBuilder methodBuilder = typeBuilder.DefineMethod(
"Main", MethodAttributes.Public | MethodAttributes.Static,
typeof(void), new Type[] { typeof(string[]) });
ILGenerator gen = methodBuilder.GetILGenerator();
gen.Emit(OpCodes.Ldstr, "Hello, World!");
gen.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
gen.Emit(OpCodes.Ldc_I4_1);
gen.Emit(OpCodes.Call, typeof(Console).GetMethod("ReadKey", new Type[] { typeof(bool) }));
assemblyBuilder.SetEntryPoint(methodBuilder, PEFileKinds.ConsoleApplication);
File.Delete("test.exe");
assemblyBuilder.Save("test.exe");
Process.Start("test.exe");
}
}
}
Итак, вопрос: как я могу установить точку входа к главному методу я определяю?
Спасибо! Это исправило это! Я также узнал, что мне нужно Opcodes.Pop возвращаемое значение Console.ReadKey и команда Opcodes.Ret, чтобы заставить все работать. – feralin
Вы знаете, почему ModuleBuilder хочет имя файла? Нужно ли быть таким же, как значение, которое я передаю AssemblyBuilder.Save()? – feralin
Я считаю, что это связано с плохим выбором перегрузок для DefineDynamicModule - согласно MSDN, две перегрузки создают переходные процессы, а два создают устойчивый модуль. Имя файла должно быть одинаковым, иначе приложение также потерпит неудачу. Указание имени файла в двух местах происходит от возможности создания сборки из нескольких модулей/файлов. – Alexander