using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
using VALUE = System.Int32;
using ID = System.Int32;

namespace Ruby
{
    [StructLayout(LayoutKind.Sequential)]
    internal struct RBasic
    {
        public uint flags;
        public VALUE klass;

        internal RBasic(uint flags, VALUE klass)
        {
            this.flags = flags;
            this.klass = klass;
        }
    }

    /// <summary>
    /// Ruby のポーティング。
    /// </summary>
    /// <remarks>
    /// 行き当たりばったりで機能を追加しています。
    /// </remarks>
    internal static class RUBY
    {
        /// <summary>
        /// DLL ファイルのパスです。
        /// </summary>
        public const string RubyDll = "msvcrt-ruby18";

        /// <summary>
        /// Ruby スクリプトを解釈するときのエンコーディングを取得または設定します。
        /// </summary>
        public static Encoding Encoding
        {
            get { return encoding; }
            set { encoding = value; }
        }
        private static Encoding encoding = Encoding.UTF8;

        /// <summary>
        /// C 用に文字列を byte の配列に変換します。
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        private static byte[] ToCBytes(string str)
        {
            return Encoding.GetBytes(str + '\0');
        }

        //
        // Q*
        // 
        public const int Qfalse = (VALUE)0;
        public const int Qtrue = (VALUE)2;
        public const int Qnil = (VALUE)4;
        public const int Qundef = (VALUE)6;

        //
        // T_*
        // 
        public const int T_NONE = 0x00;

        public const int T_NIL = 0x01;
        public const int T_OBJECT = 0x02;
        public const int T_CLASS = 0x03;
        public const int T_ICLASS = 0x04;
        public const int T_MODULE = 0x05;
        public const int T_FLOAT = 0x06;
        public const int T_STRING = 0x07;
        public const int T_REGEXP = 0x08;
        public const int T_ARRAY = 0x09;
        public const int T_FIXNUM = 0x0a;
        public const int T_HASH = 0x0b;
        public const int T_STRUCT = 0x0c;
        public const int T_BIGNUM = 0x0d;
        public const int T_FILE = 0x0e;

        public const int T_TRUE = 0x20;
        public const int T_FALSE = 0x21;
        public const int T_DATA = 0x22;
        public const int T_MATCH = 0x23;
        public const int T_SYMBOL = 0x24;

        public const int T_BLKTAG = 0x3b;
        public const int T_UNDEF = 0x3c;
        public const int T_VARMAP = 0x3d;
        public const int T_SCOPE = 0x3e;
        public const int T_NODE = 0x3f;

        public const int T_MASK = 0x3f;

        //
        // ruby_*
        //
        [DllImport(RubyDll)]
        public static extern void ruby_init();

        //
        // rb_eval*
        // 
        [DllImport(RubyDll)]
        public static extern VALUE rb_eval_string(byte[] script_string);
        public static VALUE rb_eval_string(string script_string)
        {
            return rb_eval_string(ToCBytes(script_string));
        }
        [DllImport(RubyDll)]
        public static extern VALUE rb_eval_string_protect(byte[] script, ref VALUE pstate);

        //
        // type
        //
        [DllImport(RubyDll)]
        private static extern void rb_check_type(VALUE val, int type);
        public static void Check_Type(VALUE val, int type)
        {
            rb_check_type(val, type);
        }
        private unsafe static int rb_type(VALUE obj)
        {
            if ((obj & 0x01) != 0) return T_FIXNUM;
            if (obj == Qnil) return T_NIL;
            if (obj == Qfalse) return T_FALSE;
            if (obj == Qtrue) return T_TRUE;
            if (obj == Qundef) return T_UNDEF;
            if ((obj & 0xff) == 0x0e) return T_SYMBOL;
            return (int)(((RBasic*)obj)->flags & T_MASK);
        }
        public static int TYPE(VALUE val)
        {
            return rb_type(val);
        }

        //
        // 数値
        // (int が 32 bit でないと不具合が生じうる)
        //
        public const int FIXNUM_FLAG = 0x01;
        public const int FIXNUM_MAX = int.MaxValue >> 1;
        public const int FIXNUM_MIN = int.MinValue >> 1;
        public static bool FIXNUM_P(VALUE val)
        {
            return (val & FIXNUM_FLAG) != 0;
        }
        [DllImport(RubyDll)]
        private static extern VALUE rb_int2inum(Int32 i);
        public static VALUE INT2NUM(Int32 i)
        {
            if (FIXNUM_MIN <= i && i <= FIXNUM_MAX)
                return (i << 1) | FIXNUM_FLAG;
            return rb_int2inum(i);
        }
        [DllImport(RubyDll)]
        private static extern VALUE rb_ll2inum(Int64 i);
        public static VALUE LL2NUM(Int64 i)
        {
            if (FIXNUM_MIN <= i && i <= FIXNUM_MAX)
                return ((int)i << 1) | FIXNUM_FLAG;
            return rb_ll2inum(i);
        }
        [DllImport(RubyDll)]
        private static extern int rb_num2int(VALUE val);
        public static int NUM2INT(VALUE val)
        {
            if (FIXNUM_P(val))
                return val >> 1;
            return rb_num2int(val);
        }
        [DllImport(RubyDll, EntryPoint = "rb_num2dbl")]
        public static extern double NUM2DBL(VALUE val);
        [DllImport(RubyDll)]
        public static extern VALUE rb_float_new(double dbl);
        [DllImport(RubyDll, EntryPoint = "rb_num2ll")]
        private static extern Int64 rb_num2ll(VALUE val);
        public static Int64 NUM2LL(VALUE val)
        {
            if (FIXNUM_P(val))
                return val >> 1;
            return rb_num2ll(val);
        }

        //
        // 文字列
        //
        [DllImport(RubyDll)]
        private static extern VALUE rb_str_new2(byte[] ptr);
        public static VALUE rb_str_new2(string ptr)
        {
            return rb_str_new2(ToCBytes(ptr));
        }
        [DllImport(RubyDll)]
        private static extern IntPtr rb_string_value_cstr(ref VALUE v_ptr);
        public static string StringValuePtr(VALUE v)
        {
            RUBY.Check_Type(v, RUBY.T_STRING);
            int length = 0;
            IntPtr ptr = rb_string_value_cstr(ref v);
            unsafe
            {
                byte* p = (byte*)ptr;
                while (*p != 0)
                {
                    length++;
                    p++;
                }
            }
            byte[] bytes = new byte[length];
            Marshal.Copy(ptr, bytes, 0, length);
            return Encoding.GetString(bytes);
        }

        //
        // Symbol
        //
        [DllImport(RubyDll)]
        private static extern ID rb_intern(byte[] name);
        public static ID rb_intern(string name)
        {
            return rb_intern(ToCBytes(name));
        }
        [DllImport(RubyDll, EntryPoint = "rb_to_id")]
        private static extern ID rb_to_id_(VALUE symbol);
        public static ID rb_to_id(VALUE symbol)
        {
            RUBY.Check_Type(symbol, RUBY.T_SYMBOL);
            return rb_to_id_(symbol);
        }

        public static VALUE rb_cObject
        {
            get
            {
                if (rb_cObject_ == 0)
                    rb_cObject_ = rb_eval_string("Object");
                return rb_cObject_;
            }
        }
        private static VALUE rb_cObject_ = 0;

        //
        // 定数
        //
        [DllImport(RubyDll)]
        public static extern void rb_define_const(VALUE klass, string name, VALUE val);
        [DllImport(RubyDll)]
        public static extern void rb_define_global_const(string name, VALUE val);
        [DllImport(RubyDll)]
        public static extern VALUE rb_const_get(VALUE obj, ID id);
        public static VALUE rb_const_get(VALUE obj, string name)
        {
            return rb_const_get(obj, RUBY.rb_intern(name));
        }

        //
        // module, class
        //
        [DllImport(RubyDll)]
        public static extern VALUE rb_define_class(string name, VALUE super);
        public static VALUE rb_define_class(string name)
        {
            return rb_define_class(name, rb_cObject);
        }
        [DllImport(RubyDll)]
        public static extern VALUE rb_define_class_under(VALUE module, string name, VALUE super);
        [DllImport(RubyDll)]
        public static extern VALUE rb_define_module(string name);
        [DllImport(RubyDll)]
        public static extern VALUE rb_define_module_under(VALUE module, string name);
        [DllImport(RubyDll)]
        public static extern void rb_include_module(VALUE klass, VALUE module);
        [DllImport(RubyDll)]
        public static extern void rb_extend_object(VALUE obj, VALUE module);

        //
        // コールバック
        // 
        public delegate VALUE CallbackArg0(VALUE self);
        public delegate VALUE CallbackArg1(VALUE self, VALUE arg1);
        public delegate VALUE CallbackArg2(VALUE self, VALUE arg1, VALUE arg2);
        public delegate VALUE CallbackArg3(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3);
        public delegate VALUE CallbackArg4(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4);
        public delegate VALUE CallbackArg5(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4, VALUE arg5);
        public delegate VALUE CallbackArg15(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4, VALUE arg5, VALUE arg6, VALUE arg7, VALUE arg8, VALUE arg9, VALUE arg10, VALUE arg11, VALUE arg12, VALUE arg13, VALUE arg14, VALUE arg15);

        //
        // rb_scan_args
        //
        [DllImport(RubyDll)]
        public static extern int rb_scan_args(int argc, IntPtr argv, string format, out VALUE arg1);
        [DllImport(RubyDll)]
        public static extern int rb_scan_args(int argc, IntPtr argv, string format, out VALUE arg1, out VALUE arg2);
        [DllImport(RubyDll)]
        public static extern int rb_scan_args(int argc, IntPtr argv, string format, out VALUE arg1, out VALUE arg2, out VALUE arg3);
        [DllImport(RubyDll)]
        public static extern int rb_scan_args(int argc, IntPtr argv, string format, out VALUE arg1, out VALUE arg2, out VALUE arg3, out VALUE arg4);

        //
        // メソッド
        //
        [DllImport(RubyDll)]
        private static extern void rb_define_method(VALUE klass, string name, CallbackArg0 func, int argc);
        public static void rb_define_method(VALUE klass, string name, CallbackArg0 func)
        {
            MethodDelegates.Add(func);
            rb_define_method(klass, name, func, 0);
        }
        [DllImport(RubyDll)]
        private static extern void rb_define_method(VALUE klass, string name, CallbackArg1 func, int argc);
        public static void rb_define_method(VALUE klass, string name, CallbackArg1 func)
        {
            MethodDelegates.Add(func);
            rb_define_method(klass, name, func, 1);
        }
        [DllImport(RubyDll)]
        private static extern void rb_define_method(VALUE klass, string name, CallbackArg2 func, int argc);
        public static void rb_define_method(VALUE klass, string name, CallbackArg2 func)
        {
            MethodDelegates.Add(func);
            rb_define_method(klass, name, func, 2);
        }
        [DllImport(RubyDll)]
        private static extern void rb_define_method(VALUE klass, string name, CallbackArg3 func, int argc);
        public static void rb_define_method(VALUE klass, string name, CallbackArg3 func)
        {
            MethodDelegates.Add(func);
            rb_define_method(klass, name, func, 3);
        }
        [DllImport(RubyDll)]
        private static extern void rb_define_method(VALUE klass, string name, CallbackArg4 func, int argc);
        public static void rb_define_method(VALUE klass, string name, CallbackArg4 func)
        {
            MethodDelegates.Add(func);
            rb_define_method(klass, name, func, 4);
        }
        [DllImport(RubyDll)]
        private static extern void rb_define_method(VALUE klass, string name, CallbackArg5 func, int argc);
        public static void rb_define_method(VALUE klass, string name, CallbackArg5 func)
        {
            MethodDelegates.Add(func);
            rb_define_method(klass, name, func, 5);
        }

        //
        // private メソッド
        //
        [DllImport(RubyDll)]
        private static extern void rb_define_private_method(VALUE klass, string name, CallbackArg0 func, int argc);
        public static void rb_define_private_method(VALUE klass, string name, CallbackArg0 func)
        {
            MethodDelegates.Add(func);
            rb_define_private_method(klass, name, func, 0);
        }
        [DllImport(RubyDll)]
        private static extern void rb_define_private_method(VALUE klass, string name, CallbackArg1 func, int argc);
        public static void rb_define_private_method(VALUE klass, string name, CallbackArg1 func)
        {
            MethodDelegates.Add(func);
            rb_define_private_method(klass, name, func, 1);
        }
        [DllImport(RubyDll)]
        private static extern void rb_define_private_method(VALUE klass, string name, CallbackArg2 func, int argc);
        public static void rb_define_private_method(VALUE klass, string name, CallbackArg2 func)
        {
            MethodDelegates.Add(func);
            rb_define_private_method(klass, name, func, 2);
        }
        [DllImport(RubyDll)]
        private static extern void rb_define_private_method(VALUE klass, string name, CallbackArg3 func, int argc);
        public static void rb_define_private_method(VALUE klass, string name, CallbackArg3 func)
        {
            MethodDelegates.Add(func);
            rb_define_private_method(klass, name, func, 3);
        }
        [DllImport(RubyDll)]
        private static extern void rb_define_private_method(VALUE klass, string name, CallbackArg4 func, int argc);
        public static void rb_define_private_method(VALUE klass, string name, CallbackArg4 func)
        {
            MethodDelegates.Add(func);
            rb_define_private_method(klass, name, func, 4);
        }
        [DllImport(RubyDll)]
        private static extern void rb_define_private_method(VALUE klass, string name, CallbackArg15 func, int argc);
        public static void rb_define_private_method(VALUE klass, string name, CallbackArg15 func)
        {
            MethodDelegates.Add(func);
            rb_define_private_method(klass, name, func, 15);
        }


        //
        // モジュール関数
        //
        [DllImport(RubyDll)]
        private static extern void rb_define_module_function(VALUE module, string name, CallbackArg0 func, int argc);
        public static void rb_define_module_function(VALUE module, string name, CallbackArg0 func)
        {
            MethodDelegates.Add(func);
            rb_define_module_function(module, name, func, 0);
        }
        [DllImport(RubyDll)]
        private static extern void rb_define_module_function(VALUE module, string name, CallbackArg1 func, int argc);
        public static void rb_define_module_function(VALUE module, string name, CallbackArg1 func)
        {
            MethodDelegates.Add(func);
            rb_define_module_function(module, name, func, 1);
        }
        [DllImport(RubyDll)]
        private static extern void rb_define_module_function(VALUE module, string name, CallbackArg2 func, int argc);
        public static void rb_define_module_function(VALUE module, string name, CallbackArg2 func)
        {
            MethodDelegates.Add(func);
            rb_define_module_function(module, name, func, 2);
        }
        [DllImport(RubyDll)]
        private static extern void rb_define_module_function(VALUE module, string name, CallbackArg3 func, int argc);
        public static void rb_define_module_function(VALUE module, string name, CallbackArg3 func)
        {
            MethodDelegates.Add(func);
            rb_define_module_function(module, name, func, 3);
        }

        //
        // singleton メソッド
        //
        [DllImport(RubyDll)]
        private static extern void rb_define_singleton_method(VALUE obj, string name, CallbackArg0 func, int argc);
        public static void rb_define_singleton_method(VALUE obj, string name, CallbackArg0 func)
        {
            MethodDelegates.Add(func);
            rb_define_singleton_method(obj, name, func, 0);
        }
        [DllImport(RubyDll)]
        private static extern void rb_define_singleton_method(VALUE obj, string name, CallbackArg1 func, int argc);
        public static void rb_define_singleton_method(VALUE obj, string name, CallbackArg1 func)
        {
            MethodDelegates.Add(func);
            rb_define_singleton_method(obj, name, func, 1);
        }
        [DllImport(RubyDll)]
        private static extern void rb_define_singleton_method(VALUE obj, string name, CallbackArg2 func, int argc);
        public static void rb_define_singleton_method(VALUE obj, string name, CallbackArg2 func)
        {
            MethodDelegates.Add(func);
            rb_define_singleton_method(obj, name, func, 2);
        }
        [DllImport(RubyDll)]
        private static extern void rb_define_singleton_method(VALUE obj, string name, CallbackArg3 func, int argc);
        public static void rb_define_singleton_method(VALUE obj, string name, CallbackArg3 func)
        {
            MethodDelegates.Add(func);
            rb_define_singleton_method(obj, name, func, 3);
        }
        [DllImport(RubyDll)]
        private static extern void rb_define_singleton_method(VALUE obj, string name, CallbackArg4 func, int argc);
        public static void rb_define_singleton_method(VALUE obj, string name, CallbackArg4 func)
        {
            MethodDelegates.Add(func);
            rb_define_singleton_method(obj, name, func, 4);
        }
        [DllImport(RubyDll)]
        private static extern void rb_define_singleton_method(VALUE obj, string name, CallbackArg5 func, int argc);
        public static void rb_define_singleton_method(VALUE obj, string name, CallbackArg5 func)
        {
            MethodDelegates.Add(func);
            rb_define_singleton_method(obj, name, func, 5);
        }

        //
        // funcall
        //
        [DllImport(RubyDll, EntryPoint = "rb_funcall")]
        private static extern VALUE rb_funcall_(VALUE recv, ID mid, int argc);
        public static VALUE rb_funcall(VALUE recv, ID mid)
        {
            return rb_funcall_(recv, mid, 0);
        }
        [DllImport(RubyDll, EntryPoint="rb_funcall")]
        private static extern VALUE rb_funcall_(VALUE recv, ID mid, int argc, VALUE arg1);
        public static VALUE rb_funcall(VALUE recv, ID mid, VALUE arg1)
        {
            return rb_funcall_(recv, mid, 1, arg1);
        }
        [DllImport(RubyDll, EntryPoint = "rb_funcall")]
        private static extern VALUE rb_funcall_(VALUE recv, ID mid, int argc, VALUE arg1, VALUE arg2);
        public static VALUE rb_funcall(VALUE recv, ID mid, VALUE arg1, VALUE arg2)
        {
            return rb_funcall_(recv, mid, 2, arg1, arg2);
        }
        [DllImport(RubyDll, EntryPoint = "rb_funcall")]
        private static extern VALUE rb_funcall_(VALUE recv, ID mid, int argc, VALUE arg1, VALUE arg2, VALUE arg3);
        public static VALUE rb_funcall(VALUE recv, ID mid, VALUE arg1, VALUE arg2, VALUE arg3)
        {
            return rb_funcall_(recv, mid, 3, arg1, arg2, arg3);
        }
        [DllImport(RubyDll, EntryPoint = "rb_funcall")]
        private static extern VALUE rb_funcall_(VALUE recv, ID mid, int argc, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4);
        public static VALUE rb_funcall(VALUE recv, ID mid, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4)
        {
            return rb_funcall_(recv, mid, 4, arg1, arg2, arg3, arg4);
        }
        [DllImport(RubyDll, EntryPoint = "rb_funcall")]
        private static extern VALUE rb_funcall_(VALUE recv, ID mid, int argc, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4, VALUE arg5);
        public static VALUE rb_funcall(VALUE recv, ID mid, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4, VALUE arg5)
        {
            return rb_funcall_(recv, mid, 4, arg1, arg2, arg3, arg4, arg5);
        }

        //
        // call_super
        //
        [DllImport(RubyDll, EntryPoint = "rb_call_super")]
        public static extern VALUE rb_call_super2(); // 引数省略
        [DllImport(RubyDll, EntryPoint = "rb_call_super")]
        private static extern VALUE rb_call_super_(int argc);
        public static VALUE rb_call_super()
        {
            return rb_call_super_(0);
        }
        [DllImport(RubyDll, EntryPoint = "rb_call_super")]
        private static extern VALUE rb_call_super_(int argc, VALUE arg1);
        public static VALUE rb_call_super(VALUE arg1)
        {
            return rb_call_super_(1, arg1);
        }
        [DllImport(RubyDll, EntryPoint = "rb_call_super")]
        private static extern VALUE rb_call_super_(int argc, VALUE arg1, VALUE arg2);
        public static VALUE rb_call_super(VALUE arg1, VALUE arg2)
        {
            return rb_call_super_(2, arg1, arg2);
        }
        [DllImport(RubyDll, EntryPoint = "rb_call_super")]
        private static extern VALUE rb_call_super_(int argc, VALUE arg1, VALUE arg2, VALUE arg3);
        public static VALUE rb_call_super(VALUE arg1, VALUE arg2, VALUE arg3)
        {
            return rb_call_super_(3, arg1, arg2, arg3);
        }

        //
        // 変数
        //
        [DllImport(RubyDll)]
        public static extern VALUE rb_ivar_get(VALUE obj, ID id);
        [DllImport(RubyDll)]
        public static extern VALUE rb_ivar_set(VALUE obj, ID id, VALUE val);
        [DllImport(RubyDll)]
        public static extern VALUE rb_iv_get(VALUE obj, string name);
        [DllImport(RubyDll)]
        public static extern VALUE rb_iv_set(VALUE obj, string name, VALUE val);
        [DllImport(RubyDll)]
        public static extern void rb_define_variable(string name, ref VALUE var);

        //
        // 配列
        //
        [DllImport(RubyDll)]
        public static extern VALUE rb_ary_new();
        [DllImport(RubyDll)]
        public static extern void rb_ary_push(VALUE ary, VALUE val);

        //
        // Hash
        //
        [DllImport(RubyDll)]
        public static extern VALUE rb_hash_new();
        [DllImport(RubyDll)]
        public static extern VALUE rb_hash_aref(VALUE self, VALUE key);
        [DllImport(RubyDll)]
        public static extern VALUE rb_hash_aset(VALUE self, VALUE key, VALUE value);

        //
        // 例外
        //
        [DllImport(RubyDll)]
        private static extern void rb_raise(VALUE exception, byte[] message);
        public static void rb_raise(VALUE exception, string message)
        {
            rb_raise(exception, ToCBytes(message));
        }

        //
        // そのほか
        //
        private const int FL_FREEZE = (1 << 10);

        [DllImport(RubyDll)]
        public static extern VALUE rb_inspect(VALUE obj);
        public static unsafe void rb_check_frozen(VALUE obj)
        {
            if ((((RBasic*)obj)->flags & FL_FREEZE) != 0)
                rb_error_frozen(obj);
        }
        [DllImport(RubyDll)]
        public static extern void rb_error_frozen(VALUE obj);
        [DllImport(RubyDll)]
        public static extern VALUE rb_obj_init_copy(VALUE obj, VALUE orig);
        [DllImport(RubyDll)]
        public static extern VALUE rb_define_alias(VALUE module, string newName, string oldName);
        
        //
        // 便利な関数
        //
        public static VALUE Intern(string str)
        {
            VALUE symbol;
            if (SymbolCache.TryGetValue(str, out symbol))
                return symbol;
            else
                return SymbolCache[str] = RUBY.Send(RUBY.rb_str_new2(str), "intern");
        }
        private static Dictionary<string, VALUE> SymbolCache = new Dictionary<string, int>();
        public static VALUE HashAref(VALUE hash, string key)
        {
            return RUBY.rb_hash_aref(hash, RUBY.Intern(key));
        }
        public static bool ToBool(VALUE obj)
        {
            return obj != Qnil && obj != Qfalse;
        }
        public static VALUE Send(VALUE recv, string methodName)
        {
            return rb_funcall(recv, rb_intern(methodName));
        }
        public static VALUE Send(VALUE recv, string methodName, VALUE arg1)
        {
            return rb_funcall(recv, rb_intern(methodName), arg1);
        }
        public static VALUE Send(VALUE recv, string methodName, VALUE arg1, VALUE arg2)
        {
            return rb_funcall(recv, rb_intern(methodName), arg1, arg2);
        }
        public static VALUE Send(VALUE recv, string methodName, VALUE arg1, VALUE arg2, VALUE arg3)
        {
            return rb_funcall(recv, rb_intern(methodName), arg1, arg2, arg3);
        }
        public static VALUE Send(VALUE recv, string methodName, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4)
        {
            return rb_funcall(recv, rb_intern(methodName), arg1, arg2, arg3, arg4);
        }
        public static VALUE Send(VALUE recv, string methodName, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4, VALUE arg5)
        {
            return rb_funcall(recv, rb_intern(methodName), arg1, arg2, arg3, arg4, arg5);
        }

        /// <summary>
        /// GC に回収されないための、デリゲートの参照です。
        /// </summary>
        private static List<Delegate> MethodDelegates = new List<Delegate>();
    }
}
