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); }
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); }
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); }
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); }
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; } }
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; } }
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; }
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; }