2 using System
.Runtime
.InteropServices
;
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
39 public Int32 b
; /* PRBool */
46 [FieldOffset(0),MarshalAs(UnmanagedType
.LPStr
)]
50 [StructLayout(LayoutKind
.Explicit
)]
54 public XPTCMiniVariant val
;
59 [FieldOffset(12)] /* XXX assumes 4-byte IntPtr! */
68 static void MarshalOneArg(ParamDescriptor param
, object arg
,
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 " +
85 param
.ToString() + ")");
89 throw new Exception(param
.Name() +
90 ": null passed as arg for " +
95 if (type
.IsScalar()) {
97 XPTCVariant variant
= new XPTCVariant();
100 variant
.ptr
= IntPtr
.Zero
;
101 Marshal
.StructureToPtr(variant
, buffer
, false);
114 Marshal
.WriteInt32(buffer
, (Int32
)arg
);
119 Marshal
.WriteInt64(buffer
, (Int64
)arg
);
124 Marshal
.WriteInt32(buffer
, b
? 1 : 0);
128 float[] f
= new float[] { (float)arg }
;
129 Marshal
.Copy(f
, 0, buffer
, 1);
132 double[] d
= new double[] { (double)arg }
;
133 Marshal
.Copy(d
, 0, buffer
, 1);
137 Marshal
.WriteIntPtr(buffer
,
138 Marshal
.StringToCoTaskMemAnsi((string)arg
));
140 case TypeTag
.WString
:
141 Marshal
.WriteIntPtr(buffer
,
142 Marshal
.StringToCoTaskMemUni((string)arg
));
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(),
156 if (type
.tag
== TypeTag
.Interface
) {
157 Guid iid
= param
.GetIID();
158 Console
.WriteLine("{0} is interface {1}",
160 Marshal
.WriteIntPtr(buffer
, CLRWrapper
.Wrap(arg
, ref iid
));
161 Console
.WriteLine("{0} @ {1:X2}", param
.Name(),
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
,
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
,
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
);
205 static void FreeOneMarshalledArg(ParamDescriptor param
, IntPtr buffer
)
209 static void DemarshalArgs(MethodDescriptor desc
,
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
,
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
);
254 throw new Exception(String
.Format("XPCOM Error: {0:X2}",
261 } // namespace Mozilla.XPCOM