PythonでやったJITをC#に移植しました。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の定義は以下を参照しました。(一部改変)
- http://pinvoke.net/default.aspx/kernel32.VirtualAlloc
- http://pinvoke.net/default.aspx/kernel32.VirtualFree
Delgにcdeclを指定しているのがポイントです。delegateについては以下にまとめられています。