Import from 1.9a8 tarball
[mozilla-extra.git] / extensions / mono / src / xptinvoke.cs
blob54cf5f1bd52d4dd7b9e6ca6a7d7f28bb49ac9fa3
1 using System;
2 using System.Runtime.InteropServices;
3 using Mozilla.XPCOM;
4 using System.Globalization;
6 using MethodDescriptor = Mozilla.XPCOM.TypeInfo.MethodDescriptor;
7 using ParamDescriptor = Mozilla.XPCOM.TypeInfo.ParamDescriptor;
8 using ParamFlags = Mozilla.XPCOM.TypeInfo.ParamFlags;
9 using TypeDescriptor = Mozilla.XPCOM.TypeInfo.TypeDescriptor;
10 using TypeFlags = Mozilla.XPCOM.TypeInfo.TypeFlags;
11 using TypeTag = Mozilla.XPCOM.TypeInfo.TypeTag;
13 namespace Mozilla.XPCOM {
15 [StructLayout(LayoutKind.Explicit)]
16 struct XPTCMiniVariant
18 [FieldOffset(0)]
19 public sbyte i8;
20 [FieldOffset(0)]
21 public Int16 i16;
22 [FieldOffset(0)]
23 public Int32 i32;
24 [FieldOffset(0)]
25 public Int64 i64;
26 [FieldOffset(0)]
27 public byte u8;
28 [FieldOffset(0)]
29 public UInt16 u16;
30 [FieldOffset(0)]
31 public UInt32 u32;
32 [FieldOffset(0)]
33 public UInt64 u64;
34 [FieldOffset(0)]
35 public float f;
36 [FieldOffset(0)]
37 public double d;
38 [FieldOffset(0)]
39 public Int32 b; /* PRBool */
40 [FieldOffset(0)]
41 public byte c;
42 [FieldOffset(0)]
43 public char wc;
44 [FieldOffset(0)]
45 public IntPtr p;
46 [FieldOffset(0),MarshalAs(UnmanagedType.LPStr)]
47 public string str;
50 [StructLayout(LayoutKind.Explicit)]
51 struct XPTCVariant
53 [FieldOffset(0)]
54 public XPTCMiniVariant val;
56 [FieldOffset(8)]
57 public IntPtr ptr;
59 [FieldOffset(12)] /* XXX assumes 4-byte IntPtr! */
60 public XPTType type;
62 [FieldOffset(13)]
63 public sbyte flags;
66 public class Invoker
68 static void MarshalOneArg(ParamDescriptor param, object arg,
69 IntPtr buffer)
71 string msg;
72 if (param.flags != TypeInfo.ParamFlags.In) {
73 msg = String.Format("{0} is {1} (only In " +
74 "supported)", param.Name(),
75 param.flags.ToString());
76 throw new Exception(msg);
79 TypeInfo.TypeDescriptor type = param.type;
81 if ((type.flags & TypeFlags.Reference) != 0) {
82 if ((type.flags & TypeFlags.Pointer) == 0) {
83 throw new Exception("TD is Reference but " +
84 "not Pointer?! (" +
85 param.ToString() + ")");
88 if (arg == null) {
89 throw new Exception(param.Name() +
90 ": null passed as arg for " +
91 "Reference param");
95 if (type.IsScalar()) {
97 XPTCVariant variant = new XPTCVariant();
98 variant.type = type;
99 variant.flags = 0;
100 variant.ptr = IntPtr.Zero;
101 Marshal.StructureToPtr(variant, buffer, false);
103 IntPtr p;
104 switch (type.tag) {
106 case TypeTag.Int8:
107 case TypeTag.Int16:
108 case TypeTag.Int32:
109 case TypeTag.UInt8:
110 case TypeTag.UInt16:
111 case TypeTag.UInt32:
112 case TypeTag.Char:
113 case TypeTag.WChar:
114 Marshal.WriteInt32(buffer, (Int32)arg);
115 break;
117 case TypeTag.UInt64:
118 case TypeTag.Int64:
119 Marshal.WriteInt64(buffer, (Int64)arg);
120 break;
122 case TypeTag.Bool:
123 bool b = (bool)arg;
124 Marshal.WriteInt32(buffer, b ? 1 : 0);
125 break;
127 case TypeTag.Float:
128 float[] f = new float[] { (float)arg };
129 Marshal.Copy(f, 0, buffer, 1);
130 break;
131 case TypeTag.Double:
132 double[] d = new double[] { (double)arg };
133 Marshal.Copy(d, 0, buffer, 1);
134 break;
136 case TypeTag.String:
137 Marshal.WriteIntPtr(buffer,
138 Marshal.StringToCoTaskMemAnsi((string)arg));
139 break;
140 case TypeTag.WString:
141 Marshal.WriteIntPtr(buffer,
142 Marshal.StringToCoTaskMemUni((string)arg));
143 break;
145 default:
146 msg = String.Format("{0}: type {1} not supported",
147 param.Name(), type.tag.ToString());
148 throw new Exception(msg);
151 Console.WriteLine("{0} @ {1:X2}", param.Name(),
152 buffer.ToInt32());
153 return;
156 if (type.tag == TypeTag.Interface) {
157 Guid iid = param.GetIID();
158 Console.WriteLine("{0} is interface {1}",
159 param.Name(), iid);
160 Marshal.WriteIntPtr(buffer, CLRWrapper.Wrap(arg, ref iid));
161 Console.WriteLine("{0} @ {1:X2}", param.Name(),
162 buffer.ToInt32());
163 return;
166 msg = String.Format("{0} type {1} not yet supported ",
167 param.Name(), type.tag.ToString());
168 throw new Exception(msg);
171 [DllImport("xpcom-dotnet.so")]
172 public static extern IntPtr WrapCLRObject(IntPtr obj, Guid id);
174 [DllImport("xpcom-dotnet.so")]
175 static extern IntPtr typeinfo_WrapUnicode(IntPtr str,
176 UInt32 length);
178 [DllImport("xpcom-dotnet.so")]
179 static extern void typeinfo_FreeWrappedUnicode(IntPtr str);
181 static IntPtr MarshalArgs(MethodDescriptor desc, object[] args)
183 if (args.Length != desc.args.Length) {
184 string msg = String.Format("{0} needs {1} args, {2} passed",
185 desc.name, desc.args.Length,
186 args.Length);
187 throw new Exception(msg);
190 int variantsz = 16; /* sizeof(nsXPTCVariant) */
191 int size = variantsz * args.Length;
192 IntPtr argbuf = Marshal.AllocCoTaskMem(size);
194 for (int i = 0; i < args.Length; i++) {
195 ParamDescriptor param = desc.args[i];
196 IntPtr current = (IntPtr)(argbuf.ToInt32() + variantsz * i);
197 object arg = args[i];
199 MarshalOneArg(param, arg, current);
202 return argbuf;
205 static void FreeOneMarshalledArg(ParamDescriptor param, IntPtr buffer)
209 static void DemarshalArgs(MethodDescriptor desc,
210 IntPtr argbuf)
212 int variantsz = Marshal.SizeOf(typeof(XPTCVariant));
213 for (int i = 0; i < desc.args.Length; i++) {
214 ParamDescriptor param = desc.args[i];
215 IntPtr current = (IntPtr)(argbuf.ToInt32() + variantsz * i);
216 FreeOneMarshalledArg(param, current);
218 Marshal.FreeCoTaskMem(argbuf);
221 public static int XPTC_InvokeByIndexSafe(IntPtr that, Int32 index,
222 UInt32 argCount, IntPtr args)
224 Console.WriteLine("XPTC_IBI: {0:X2}:{1}({2}:{3:X2})",
225 that.ToInt32(), index, argCount, args.ToInt32());
226 return XPTC_InvokeByIndex(that, index, argCount, args);
229 [DllImport("libxpcom.so")]
230 static extern int XPTC_InvokeByIndex(IntPtr that, Int32 methodIndex,
231 UInt32 argCount,
232 IntPtr args);
234 public static object Invoke(IntPtr that, string iface,
235 string method, params object[] args)
237 return Invoke(that, TypeInfo.GetMethodData(iface, method), args);
240 public static object Invoke(IntPtr that, string iface,
241 int method, params object[] args)
243 return Invoke(that, TypeInfo.GetMethodData(iface, method), args);
246 public static object Invoke(IntPtr that, MethodDescriptor desc,
247 params object[] args)
249 IntPtr argbuf = MarshalArgs(desc, args);
250 int res = XPTC_InvokeByIndex(that, desc.index,
251 (UInt32)args.Length, argbuf);
252 DemarshalArgs(desc, argbuf);
253 if (res != 0) {
254 throw new Exception(String.Format("XPCOM Error: {0:X2}",
255 res));
257 return null;
261 } // namespace Mozilla.XPCOM