Question

I am writing a concatenative language in C#, and currently it is interpreted, but I want to take the next step: compiling. To start on this, I tried writing a simple "Hello, World!" program emitter using System.Reflection.Emit. The code works without any Emit exceptions, but when I run the generated "test.exe" file, it throws the exception

Unhandled Exception: System.MissingMethodException: Entry point not found in assembly 'IL_Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.

I have tried googling for the answer, but to no avail. Perhaps someone here can help me? (please) The code I wrote is below:

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");
        }
    }
}

So, the question is: how can I set the entry point to the Main method I define?

Was it helpful?

Solution

You are missing call to typeBuilder.CreateType(), DefineDynamicModule must have exe name passed as second parameter. Full working sample:

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, "test.exe");
            TypeBuilder typeBuilder = moduleBuilder.DefineType("Program", 
                TypeAttributes.Class | TypeAttributes.Public);
            MethodBuilder methodBuilder = typeBuilder.DefineMethod(
                "Main", MethodAttributes.HideBySig|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) }));
            typeBuilder.CreateType();
            assemblyBuilder.SetEntryPoint(methodBuilder, PEFileKinds.ConsoleApplication);
            File.Delete("test.exe");
            assemblyBuilder.Save("test.exe");

            Process.Start("test.exe");
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top