【お知らせ】プログラミング記事の投稿はQiitaに移行しました。

C#でJIT

PythonでやったJITC#に移植しました。32bit専用です。

using System;
using System.Runtime.InteropServices;

class Program
{
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern IntPtr VirtualAlloc(IntPtr lpAddress, int dwSize,
        int flAllocationType, int flProtect);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool VirtualFree(IntPtr lpAddress, int dwSize,
        int dwFreeType);

    const int MEM_COMMIT = 0x1000;
    const int MEM_RELEASE = 0x8000;
    const int PAGE_EXECUTE_READWRITE = 0x40;

    static byte[] codes =
    {
        0x8b, 0x44, 0x24, 0x04, // mov eax, [esp+4]
        0x03, 0x44, 0x24, 0x08, // add eax, [esp+8]
        0xc3,                   // ret
    };

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    delegate int Delg(int a, int b);

    static void Main(string[] args)
    {
        var buflen = codes.Length;
        var p = VirtualAlloc(IntPtr.Zero, buflen,
            MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        Marshal.Copy(codes, 0, p, buflen);

        var f = Marshal.GetDelegateForFunctionPointer(
            p, typeof(Delg)) as Delg;
        Console.WriteLine("f(1, 2) = {0}", f(1, 2));

        VirtualFree(p, 0, MEM_RELEASE);
    }
}

Marshalが鍵です。Marshal.GetDelegateForFunctionPointer()はジェネリック型を受け付けないためFunc<>を使用していません。

P/Invokeの定義は以下を参照しました。(一部改変)

Delgにcdeclを指定しているのがポイントです。delegateについては以下にまとめられています。