Пример #1
0
            public override void Generate(ItemData data)
            {
                var field = AddMethodArg(data, Method);

                // define a non-conflict named method that will back the given method.
                string name = Name;

                if (data.Names.Contains(name))
                {
                    name = name + "_" + (data.FID++);
                }
                data.Names.Add(name);

                // Define the new method.
                var         param = BoundTo.GetParameters();
                var         meth  = NetHelpers.CloneMethod(data.TB, name, BoundTo);
                ILGenerator gen   = meth.GetILGenerator();

                // ILuaValue[] loc = new ILuaValue[{param.length}];
                LocalBuilder loc = gen.CreateArray(typeof(ILuaValue), param.Length);

                for (int ind = 0; ind < param.Length; ind++)
                {
                    // loc[{ind}] = E.Runtime.CreateValue(arg_{ind});
                    gen.Emit(OpCodes.Ldloc, loc);
                    gen.Emit(OpCodes.Ldc_I4, ind);
                    gen.Emit(OpCodes.Ldarg_0);
                    gen.Emit(OpCodes.Ldfld, data.EnvField);
                    gen.Emit(OpCodes.Callvirt, typeof(ILuaEnvironment).GetProperty(nameof(ILuaEnvironment.Runtime)).GetGetMethod());
                    gen.Emit(OpCodes.Ldarg, ind + 1);
                    if (!param[ind].ParameterType.IsClass)
                    {
                        gen.Emit(OpCodes.Box, param[ind].ParameterType);
                    }
                    gen.Emit(OpCodes.Callvirt, typeof(ILuaRuntime).GetMethod(nameof(ILuaRuntime.CreateValue)));
                    gen.Emit(OpCodes.Stelem, typeof(ILuaValue));
                }

                // ILuaMultiValue args = E.Runtime.CreateMultiValue(loc);
                var args = gen.DeclareLocal(typeof(ILuaMultiValue));

                gen.Emit(OpCodes.Ldarg_0);
                gen.Emit(OpCodes.Ldfld, data.EnvField);
                gen.Emit(OpCodes.Callvirt, typeof(ILuaEnvironment).GetProperty(nameof(ILuaEnvironment.Runtime)).GetGetMethod());
                gen.Emit(OpCodes.Ldloc, loc);
                gen.Emit(OpCodes.Callvirt, typeof(ILuaRuntime).GetMethod(nameof(ILuaRuntime.CreateMultiValue)));
                gen.Emit(OpCodes.Stloc, args);

                CallFieldAndReturn(gen, BoundTo.ReturnType, field, args, data.EnvField);

                // link our new method to the method it's bound to.
                data.TB.DefineMethodOverride(meth, BoundTo);
                data.Methods.Add(BoundTo);
            }
Пример #2
0
        /// <summary>
        /// Creates a new method that implements the given method that throws a
        /// NotImplementedException.
        /// </summary>
        /// <param name="data">The current data.</param>
        /// <param name="method">The method to implement.</param>
        static void StubImplement(ItemData data, MethodInfo method, string name)
        {
            // we already created this method
            if (data.Methods.Contains(method))
            {
                return;
            }

            // define a no-conflict name for this method
            if (data.Names.Contains(name))
            {
                name = name + "_" + (data.FID++);
            }
            data.Names.Add(name);

            // define the new method with the same signature as the interface.
            var         meth = NetHelpers.CloneMethod(data.TB, name, method);
            ILGenerator gen  = meth.GetILGenerator();

            gen.ThrowException(typeof(NotImplementedException));

            // link our new method to be the definition of the interface method.
            data.TB.DefineMethodOverride(meth, method);
        }
Пример #3
0
        Type CreateDelegateType(MethodInfo delegateMethod)
        {
            var args = delegateMethod.GetParameters();

            TypeBuilder   tb   = NetHelpers.DefineGlobalType("$DelegateHelper");
            FieldBuilder  meth = tb.DefineField("meth", typeof(ILuaValue), FieldAttributes.Private);
            FieldBuilder  E    = tb.DefineField("E", typeof(ILuaEnvironment), FieldAttributes.Private);
            MethodBuilder mb   = NetHelpers.CloneMethod(tb, "Do", delegateMethod);
            ILGenerator   gen  = mb.GetILGenerator();

            // loc = new object[{args.Length}];
            LocalBuilder loc = gen.CreateArray(typeof(object), args.Length);

            for (int i = 0; i < args.Length; i++)
            {
                // loc[i] = arg_{i+1};
                gen.Emit(OpCodes.Ldloc, loc);
                gen.Emit(OpCodes.Ldc_I4, i);
                gen.Emit(OpCodes.Ldarg, i + 1);
                if (args[i].ParameterType.IsValueType)
                {
                    gen.Emit(OpCodes.Box, args[i].ParameterType);
                }
                gen.Emit(OpCodes.Stelem, typeof(object));
            }

            // ILuaMultiValue methodArgs = E.Runtime.CreateMultiValueFromObj(loc);
            LocalBuilder methodArgs = gen.DeclareLocal(typeof(ILuaMultiValue));

            gen.Emit(OpCodes.Ldfld, E);
            gen.Emit(OpCodes.Callvirt, typeof(ILuaEnvironment).GetProperty(nameof(ILuaEnvironment.Runtime)).GetGetMethod());
            gen.Emit(OpCodes.Ldloc, loc);
            gen.Emit(OpCodes.Callvirt, typeof(ILuaRuntime).GetMethod(nameof(ILuaRuntime.CreateMultiValueFromObj)));
            gen.Emit(OpCodes.Stloc, methodArgs);

            // ret = this.meth.Invoke(LuaNil.Nil, false, -1, methodArgs)
            LocalBuilder ret = gen.DeclareLocal(typeof(ILuaMultiValue));

            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Ldfld, meth);
            gen.Emit(OpCodes.Ldnull);
            gen.Emit(OpCodes.Ldfld, typeof(LuaNil).GetField(nameof(LuaNil.Nil), BindingFlags.Static | BindingFlags.Public));
            gen.Emit(OpCodes.Ldc_I4_0);
            gen.Emit(OpCodes.Ldc_I4_M1);
            gen.Emit(OpCodes.Ldloc, methodArgs);
            gen.Emit(OpCodes.Callvirt, typeof(ILuaValue).GetMethod(nameof(ILuaValue.Invoke)));
            gen.Emit(OpCodes.Stloc, ret);

            // Store any by-ref parameters in the arguments
            for (int i = 0; i < args.Length; i++)
            {
                if (args[i].IsOut)
                {
                    // arg_{i+1} = methodArgs[{i}].As<T>();
                    gen.Emit(OpCodes.Ldloc, methodArgs);
                    gen.Emit(OpCodes.Ldc_I4, i);
                    gen.Emit(OpCodes.Callvirt, typeof(ILuaMultiValue).GetMethod("get_Item"));
                    gen.Emit(OpCodes.Callvirt, typeof(ILuaValue).GetMethod(nameof(ILuaValue.As))
                             .MakeGenericMethod(args[i].ParameterType));
                    gen.Emit(OpCodes.Starg, i + 1);
                }
            }

            // return ret.As<{info.Return}>();
            if (delegateMethod.ReturnType != null && delegateMethod.ReturnType != typeof(void))
            {
                gen.Emit(OpCodes.Ldloc, ret);
                gen.Emit(OpCodes.Callvirt, typeof(ILuaValue).GetMethod(nameof(ILuaValue.As))
                         .MakeGenericMethod(delegateMethod.ReturnType));
            }
            gen.Emit(OpCodes.Ret);

            //// public <>_type_(ILuaEnvironment E, ILuaValue method)
            ConstructorBuilder cb = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard,
                                                         new[] { typeof(ILuaEnvironment), typeof(ILuaValue) });

            gen = cb.GetILGenerator();

            // base();
            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Call, typeof(object).GetConstructor(new Type[0]));

            // this.E = E;
            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Ldarg_1);
            gen.Emit(OpCodes.Stfld, E);

            // this.meth = method;
            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Ldarg_2);
            gen.Emit(OpCodes.Stfld, meth);
            gen.Emit(OpCodes.Ret);

            return(tb.CreateType());
        }