示例#1
0
        static IntPtr MarshalArgs(MethodDescriptor desc, object[] args)
        {
            if (args.Length != desc.args.Length)
            {
                string msg = String.Format("{0} needs {1} args, {2} passed",
                                           desc.name, desc.args.Length,
                                           args.Length);
                throw new Exception(msg);
            }

            int    variantsz = 16; /* sizeof(nsXPTCVariant) */
            int    size      = variantsz * args.Length;
            IntPtr argbuf    = Marshal.AllocCoTaskMem(size);

            for (int i = 0; i < args.Length; i++)
            {
                ParamDescriptor param   = desc.args[i];
                IntPtr          current = (IntPtr)(argbuf.ToInt32() + variantsz * i);
                object          arg     = args[i];

                MarshalOneArg(param, arg, current);
            }

            return(argbuf);
        }
示例#2
0
        static void DemarshalArgs(MethodDescriptor desc,
                                  IntPtr argbuf)
        {
            int variantsz = Marshal.SizeOf(typeof(XPTCVariant));

            for (int i = 0; i < desc.args.Length; i++)
            {
                ParamDescriptor param   = desc.args[i];
                IntPtr          current = (IntPtr)(argbuf.ToInt32() + variantsz * i);
                FreeOneMarshalledArg(param, current);
            }
            Marshal.FreeCoTaskMem(argbuf);
        }
示例#3
0
        int InvokeMethod(int index, IntPtr args)
        {
            Console.WriteLine("invoking method {0} on {1}", index,
                              wrappedObj);
            MethodDescriptor desc      = TypeInfo.GetMethodData(wrappedAsIID, index);
            Type             ifaceType = TypeInfo.TypeForIID(wrappedAsIID);
            // Console.WriteLine("ifaceType: {0}", ifaceType);
            MethodInfo meth = ifaceType.GetMethod(desc.name);

            // Console.WriteLine("meth: {0}", meth);
            // This might just throw on you, if it's not a void-taking method
            meth.Invoke(wrappedObj, new object[0]);
            return(0);
        }
示例#4
0
        public static object Invoke(IntPtr that, MethodDescriptor desc,
                                    params object[] args)
        {
            IntPtr argbuf = MarshalArgs(desc, args);
            int    res    = XPTC_InvokeByIndex(that, desc.index,
                                               (UInt32)args.Length, argbuf);

            DemarshalArgs(desc, argbuf);
            if (res != 0)
            {
                throw new Exception(String.Format("XPCOM Error: {0:X2}",
                                                  res));
            }
            return(null);
        }
示例#5
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;
            }
        }
示例#6
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;
            }
        }
示例#7
0
文件: xptinvoke.cs 项目: nfan/Jaxer
 public static object Invoke(IntPtr that, MethodDescriptor desc,
                         params object[] args)
 {
     IntPtr argbuf = MarshalArgs(desc, args);
     int res = XPTC_InvokeByIndex(that, desc.index,
                              (UInt32)args.Length, argbuf);
     DemarshalArgs(desc, argbuf);
     if (res != 0) {
     throw new Exception(String.Format("XPCOM Error: {0:X2}",
                                       res));
     }
     return null;
 }
示例#8
0
文件: xptinvoke.cs 项目: nfan/Jaxer
        static IntPtr MarshalArgs(MethodDescriptor desc, object[] args)
        {
            if (args.Length != desc.args.Length) {
            string msg = String.Format("{0} needs {1} args, {2} passed",
                                       desc.name, desc.args.Length,
                                       args.Length);
            throw new Exception(msg);
            }

            int variantsz = 16; /* sizeof(nsXPTCVariant) */
            int size = variantsz * args.Length;
            IntPtr argbuf = Marshal.AllocCoTaskMem(size);

            for (int i = 0; i < args.Length; i++) {
            ParamDescriptor param = desc.args[i];
            IntPtr current = (IntPtr)(argbuf.ToInt32() + variantsz * i);
            object arg = args[i];

            MarshalOneArg(param, arg, current);
            }

            return argbuf;
        }
示例#9
0
文件: xptinvoke.cs 项目: nfan/Jaxer
 static void DemarshalArgs(MethodDescriptor desc,
                       IntPtr argbuf)
 {
     int variantsz = Marshal.SizeOf(typeof(XPTCVariant));
     for (int i = 0; i < desc.args.Length; i++) {
     ParamDescriptor param = desc.args[i];
     IntPtr current = (IntPtr)(argbuf.ToInt32() + variantsz * i);
     FreeOneMarshalledArg(param, current);
     }
     Marshal.FreeCoTaskMem(argbuf);
 }