Exemple #1
0
 Type FixupInterfaceType(TypeInfo.ParamDescriptor desc)
 {
     try {
         return(TypeInfo.TypeForIID(desc.GetIID()));
     } catch (Exception e) {
         // Console.WriteLine(e);
         return(typeof(object));
     }
 }
Exemple #2
0
        unsafe void GenerateProxyMethod(MethodDescriptor desc)
        {
            if (!desc.IsVisible())
            {
                Console.WriteLine("HIDDEN: {0}", desc);
                return;
            }
            MethodAttributes methodAttrs =
                MethodAttributes.Public | MethodAttributes.Virtual;

            String methodName = desc.name;

            if (desc.IsGetter())
            {
                methodName   = "get_" + desc.name;
                methodAttrs |= MethodAttributes.SpecialName;
            }
            else if (desc.IsSetter())
            {
                methodName   = "set_" + desc.name;
                methodAttrs |= MethodAttributes.SpecialName;
            }

            // Fix up interface types in parameters
            Type ret = desc.resultType;

            if (ret == typeof(object))
            {
                ret = FixupInterfaceType(desc.args[desc.args.Length - 1]);
            }
            Type[] argTypes = (Type[])desc.argTypes.Clone();
            for (int i = 0; i < argTypes.Length; i++)
            {
                if (argTypes[i] == typeof(object))
                {
                    argTypes[i] = FixupInterfaceType(desc.args[i]);
                }
            }
            MethodBuilder meth = tb.DefineMethod(methodName, methodAttrs, ret, argTypes);

            ilg      = meth.GetILGenerator();
            bufLocal = ilg.DeclareLocal(System.Type.GetType("System.Int32*"));
            LocalBuilder guidLocal = ilg.DeclareLocal(typeof(System.Guid));

            TypeInfo.ParamDescriptor[] args = desc.args;

            Type marshalType = typeof(System.Runtime.InteropServices.Marshal);

            // Marshal.AllocCoTaskMem(constify(argBufSize))
            int argCount   = args.Length;
            int argBufSize = VARIANT_SIZE * args.Length;

            ilg.Emit(OpCodes.Ldc_I4, argBufSize);
            ilg.Emit(OpCodes.Call, marshalType.GetMethod("AllocCoTaskMem"));
            ilg.Emit(OpCodes.Stloc, bufLocal);

            for (int i = 0; i < argCount; i++)
            {
                TypeInfo.ParamDescriptor param = args[i];
                TypeInfo.TypeDescriptor  type  = param.type;
                IntPtr ptr   = IntPtr.Zero;
                sbyte  flags = 0;
                EmitTypeStore(type, i);

                if (param.IsOut())
                {
                    EmitOutParamPrep(type, i);
                    if (!param.IsIn())
                    {
                        continue;
                    }
                }
                switch (type.tag)
                {
                case TypeTag.Int8:
                case TypeTag.Int16:
                case TypeTag.UInt8:
                case TypeTag.UInt16:
                case TypeTag.Char:
                case TypeTag.WChar:
                case TypeTag.UInt32:
                    EmitPrepareArgStore(i);
                    // XXX do I need to cast this?
                    ilg.Emit(OpCodes.Castclass, typeof(Int32));
                    ilg.Emit(OpCodes.Stind_I4);
                    break;

                case TypeTag.Int32:
                    EmitPrepareArgStore(i);
                    ilg.Emit(OpCodes.Stind_I4);
                    break;

                case TypeTag.NSIdPtr:
                    EmitPrepareArgStore(i);
                    ilg.Emit(OpCodes.Stind_I4); // XXX 64-bitness
                    break;

                case TypeTag.String:
                    EmitPrepareArgStore(i);
                    // the string arg is now on the stack
                    ilg.Emit(OpCodes.Call,
                             marshalType.GetMethod("StringToCoTaskMemAnsi"));
                    ilg.Emit(OpCodes.Stind_I4);
                    break;

                case TypeTag.Interface:
                    EmitPrepareArgStore(i);
                    // MRP is the object passed as this arg
                    ilg.Emit(OpCodes.Ldloca_S, guidLocal);
                    ilg.Emit(OpCodes.Ldstr, param.GetIID().ToString());
                    ilg.Emit(OpCodes.Call, guidCtor);
                    ilg.Emit(OpCodes.Ldloca_S, guidLocal);
                    // stack is now objarg, ref guid
                    ilg.Emit(OpCodes.Call, typeof(CLRWrapper).GetMethod("Wrap"));
                    // now stack has the IntPtr in position to be stored.
                    ilg.Emit(OpCodes.Stind_I4);
                    break;

                default:
                    /*
                     * String msg = String.Format("{0}: type {1} not supported",
                     *                  param.Name(), type.tag.ToString());
                     * throw new Exception(msg);
                     */
                    break;
                }
                EmitPtrAndFlagsStore(i, ptr, flags);
            }

            //= (void)XPTC_InvokeByIndex(thisptr, desc.index, length, bufLocal);
            ilg.Emit(OpCodes.Ldarg_0);
            ilg.Emit(OpCodes.Ldfld, thisField);
            ilg.Emit(OpCodes.Ldc_I4, desc.index);
            ilg.Emit(OpCodes.Ldc_I4, args.Length);
            ilg.Emit(OpCodes.Ldloc_0);
            ilg.Emit(OpCodes.Call, typeof(Mozilla.XPCOM.Invoker).
                     GetMethod("XPTC_InvokeByIndex",
                               BindingFlags.Static | BindingFlags.NonPublic));
            ilg.Emit(OpCodes.Pop);

            if (ret == typeof(string))
            {
                ilg.Emit(OpCodes.Ldstr, "FAKE RETURN STRING");
            }
            else if (ret == typeof(object))
            {
                ilg.Emit(OpCodes.Newobj,
                         typeof(object).GetConstructor(new Type[0]));
            }
            else if (ret == typeof(int))
            {
                EmitLoadReturnSlot_1(args.Length);
            }
            else if (ret == typeof(void))
            {
                // Nothing
            }
            else
            {
                throw new Exception(String.Format("return type {0} not " +
                                                  "supported yet",
                                                  desc.result.type.tag));
            }

            //= Marshal.FreeCoTaskMem(bufLocal);
            ilg.Emit(OpCodes.Ldloc, bufLocal);
            ilg.Emit(OpCodes.Call, marshalType.GetMethod("FreeCoTaskMem"));

            ilg.Emit(OpCodes.Ret);

            ilg      = null;
            bufLocal = null;

            if (desc.IsSetter())
            {
                if (lastProperty != null && lastProperty.Name == desc.name)
                {
                    lastProperty.SetSetMethod(meth);
                }
                else
                {
                    tb.DefineProperty(desc.name, PROPERTY_ATTRS, desc.resultType,
                                      new Type[0]).SetSetMethod(meth);
                }
                lastProperty = null;
            }
            else if (desc.IsGetter())
            {
                lastProperty = tb.DefineProperty(desc.name, PROPERTY_ATTRS,
                                                 desc.resultType, new Type[0]);
                lastProperty.SetGetMethod(meth);
            }
            else
            {
                lastProperty = null;
            }
        }