* Typo.
[kdebindings.git] / csharp / qyoto / src / SmokeInvocation.cs
blobd75a1e45eabd409be3cb636d85fe1a356c79ed3a
1 /***************************************************************************
2 SmokeInvocation.cs - description
3 -------------------
4 begin : Wed Jun 16 2004
5 copyright : (C) 2004 by Richard Dale
6 email : richard.j.dale@gmail.com
7 ***************************************************************************/
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
18 namespace Qyoto {
19 using System;
20 using System.Collections;
21 using System.Collections.Generic;
22 using System.Diagnostics;
23 using System.Text;
24 using System.Reflection;
25 using System.Runtime.Remoting.Proxies;
26 using System.Runtime.Remoting.Messaging;
27 using System.Runtime.Remoting;
28 using System.Runtime.InteropServices;
30 public struct ModuleIndex {
31 public IntPtr smoke;
32 public short index;
35 [StructLayout(LayoutKind.Explicit)]
36 unsafe public struct StackItem {
37 [FieldOffset(0)] public void * s_voidp;
38 [FieldOffset(0)] public bool s_bool;
39 [FieldOffset(0)] public sbyte s_char;
40 [FieldOffset(0)] public byte s_uchar;
41 [FieldOffset(0)] public short s_short;
42 [FieldOffset(0)] public ushort s_ushort;
43 [FieldOffset(0)] public int s_int;
44 [FieldOffset(0)] public uint s_uint;
45 [FieldOffset(0)] public long s_long;
46 [FieldOffset(0)] public ulong s_ulong;
47 [FieldOffset(0)] public float s_float;
48 [FieldOffset(0)] public double s_double;
49 [FieldOffset(0)] public long s_enum;
50 [FieldOffset(0)] public IntPtr s_class;
53 public class SmokeInvocation {
54 [DllImport("libqyoto", CharSet=CharSet.Ansi)]
55 static extern ModuleIndex FindMethodId(string className, string mungedName, string signature);
57 [DllImport("libqyoto", CharSet=CharSet.Ansi, EntryPoint="CallSmokeMethod")]
58 static extern void CallSmokeMethod(IntPtr smoke, int methodId, IntPtr target, IntPtr sp, int items);
60 [DllImport("libqyoto", CharSet=CharSet.Ansi)]
61 static extern int QyotoHash(IntPtr obj);
63 // The key is a type name of a class which has overriden one or more
64 // virtual methods, and the value is a Hashtable of the smoke type
65 // signatures as keys retrieving a suitable MethodInfo to invoke via
66 // reflection.
67 static private Dictionary<Type, Dictionary<string, MemberInfo>> overridenMethods =
68 new Dictionary<Type, Dictionary<string, MemberInfo>>();
70 static private MethodInfo metaObjectMethod = typeof(QObject).GetMethod("MetaObject", BindingFlags.Instance | BindingFlags.Public);
72 static void AddOverridenMethods(Type klass) {
73 if (SmokeMarshallers.IsSmokeClass(klass)) {
74 return;
77 if (overridenMethods.ContainsKey(klass))
78 return;
80 Dictionary<string, MemberInfo> methodsHash = new Dictionary<string, MemberInfo>();
81 overridenMethods.Add(klass, methodsHash);
83 do {
84 MemberInfo[] methods = klass.FindMembers( MemberTypes.Method,
85 BindingFlags.Public
86 | BindingFlags.NonPublic
87 | BindingFlags.Instance
88 | BindingFlags.DeclaredOnly,
89 Type.FilterName,
90 "*" );
91 foreach (MemberInfo method in methods) {
92 Type parent = klass.BaseType;
93 string signature = null;
94 while (signature == null && parent != null && parent != typeof(Qt)) {
95 MemberInfo[] parentMethods = parent.FindMembers( MemberTypes.Method,
96 BindingFlags.Public
97 | BindingFlags.NonPublic
98 | BindingFlags.Instance
99 | BindingFlags.DeclaredOnly,
100 Type.FilterName,
101 method.Name );
102 foreach (MemberInfo parentMethod in parentMethods) {
103 if (method.ToString() == parentMethod.ToString()) {
104 object[] smokeMethod = parentMethod.GetCustomAttributes(typeof(SmokeMethod), false);
105 if (smokeMethod.Length > 0) {
106 signature = ((SmokeMethod) smokeMethod[0]).Signature;
112 parent = parent.BaseType;
115 if (signature != null && !methodsHash.ContainsKey(signature)) {
116 methodsHash.Add(signature, method);
120 klass = klass.BaseType;
121 } while (!SmokeMarshallers.IsSmokeClass(klass));
124 public static IntPtr OverridenMethod(IntPtr instance, string method) {
125 Type klass = ((GCHandle) instance).Target.GetType();
127 if (method == "metaObject() const") {
128 #if DEBUG
129 return (IntPtr) DebugGCHandle.Alloc(metaObjectMethod);
130 #else
131 return (IntPtr) GCHandle.Alloc(metaObjectMethod);
132 #endif
135 Dictionary<string, MemberInfo> methods;
136 if (!overridenMethods.TryGetValue(klass, out methods)) {
137 return (IntPtr) 0;
140 MemberInfo methodInfo;
141 if (!methods.TryGetValue(method, out methodInfo)) {
142 return (IntPtr) 0;
145 #if DEBUG
146 return (IntPtr) DebugGCHandle.Alloc(methodInfo);
147 #else
148 return (IntPtr) GCHandle.Alloc(methodInfo);
149 #endif
152 public static void InvokeMethod(IntPtr instanceHandle, IntPtr methodHandle, IntPtr stack) {
153 object instance = ((GCHandle) instanceHandle).Target;
154 MethodInfo method = (MethodInfo) ((GCHandle) methodHandle).Target;
155 #if DEBUG
156 if ( (QDebug.DebugChannel() & QtDebugChannel.QTDB_TRANSPARENT_PROXY) != 0
157 && (QDebug.DebugChannel() & QtDebugChannel.QTDB_VIRTUAL) != 0 )
159 Console.WriteLine( "ENTER InvokeMethod() {0}.{1}",
160 instance,
161 method.Name );
163 #endif
165 unsafe {
166 StackItem * stackPtr = (StackItem *) stack;
167 ParameterInfo[] parameters = method.GetParameters();
168 object[] args = new object[parameters.Length];
170 for (int i = 0; i < args.Length; i++) {
171 if (parameters[i].ParameterType == typeof(bool)) {
172 args[i] = stackPtr[i+1].s_bool;
173 } else if (parameters[i].ParameterType == typeof(sbyte)) {
174 args[i] = stackPtr[i+1].s_char;
175 } else if (parameters[i].ParameterType == typeof(byte)) {
176 args[i] = stackPtr[i+1].s_uchar;
177 } else if (parameters[i].ParameterType == typeof(short)) {
178 args[i] = stackPtr[i+1].s_short;
179 } else if (parameters[i].ParameterType == typeof(ushort)) {
180 args[i] = stackPtr[i+1].s_ushort;
181 } else if (parameters[i].ParameterType == typeof(int)) {
182 args[i] = stackPtr[i+1].s_int;
183 } else if (parameters[i].ParameterType.IsEnum) {
184 args[i] = Enum.ToObject(parameters[i].ParameterType, stackPtr[i+1].s_int);
185 } else if (parameters[i].ParameterType == typeof(uint)) {
186 args[i] = stackPtr[i+1].s_uint;
187 } else if (parameters[i].ParameterType == typeof(long)) {
188 args[i] = stackPtr[i+1].s_long;
189 } else if (parameters[i].ParameterType == typeof(ulong)) {
190 args[i] = stackPtr[i+1].s_ulong;
191 } else if (parameters[i].ParameterType == typeof(float)) {
192 args[i] = stackPtr[i+1].s_float;
193 } else if (parameters[i].ParameterType == typeof(double)) {
194 args[i] = stackPtr[i+1].s_double;
195 } else if (parameters[i].ParameterType == typeof(string)) {
196 if (stackPtr[i+1].s_class != IntPtr.Zero) {
197 args[i] = (string) ((GCHandle) stackPtr[i+1].s_class).Target;
198 #if DEBUG
199 DebugGCHandle.Free((GCHandle) stackPtr[i+1].s_class);
200 #else
201 ((GCHandle) stackPtr[i+1].s_class).Free();
202 #endif
204 } else {
205 if (stackPtr[i+1].s_class != IntPtr.Zero) {
206 args[i] = ((GCHandle) stackPtr[i+1].s_class).Target;
207 #if DEBUG
208 DebugGCHandle.Free((GCHandle) stackPtr[i+1].s_class);
209 #else
210 ((GCHandle) stackPtr[i+1].s_class).Free();
211 #endif
216 object returnValue = method.Invoke(instance, args);
217 Type returnType = method.ReturnType;
219 if (returnType == typeof(void)) {
221 } else if (returnType == typeof(bool)) {
222 stackPtr[0].s_bool = (bool) returnValue;
223 } else if (returnType == typeof(sbyte)) {
224 stackPtr[0].s_char = (sbyte) returnValue;
225 } else if (returnType == typeof(byte)) {
226 stackPtr[0].s_uchar = (byte) returnValue;
227 } else if (returnType == typeof(short)) {
228 stackPtr[0].s_short = (short) returnValue;
229 } else if (returnType == typeof(ushort)) {
230 stackPtr[0].s_ushort = (ushort) returnValue;
231 } else if (returnType == typeof(int) || returnType.IsEnum) {
232 stackPtr[0].s_int = (int) returnValue;
233 } else if (returnType == typeof(uint)) {
234 stackPtr[0].s_uint = (uint) returnValue;
235 } else if (returnType == typeof(long)) {
236 stackPtr[0].s_long = (long) returnValue;
237 } else if (returnType == typeof(ulong)) {
238 stackPtr[0].s_ulong = (ulong) returnValue;
239 } else if (returnType == typeof(float)) {
240 stackPtr[0].s_float = (float) returnValue;
241 } else if (returnType == typeof(double)) {
242 stackPtr[0].s_double = (double) returnValue;
243 } else if (returnType == typeof(string)) {
244 #if DEBUG
245 stackPtr[0].s_class = (IntPtr) DebugGCHandle.Alloc(returnValue);
246 #else
247 stackPtr[0].s_class = (IntPtr) GCHandle.Alloc(returnValue);
248 #endif
249 } else if (returnValue == null) {
250 stackPtr[0].s_class = IntPtr.Zero;
251 } else {
252 #if DEBUG
253 stackPtr[0].s_class = (IntPtr) DebugGCHandle.Alloc(returnValue);
254 #else
255 stackPtr[0].s_class = (IntPtr) GCHandle.Alloc(returnValue);
256 #endif
260 return;
263 static public void InvokeCustomSlot(IntPtr obj, string slotname, IntPtr stack, IntPtr ret) {
264 QObject qobj = (QObject) ((GCHandle)obj).Target;
265 #if DEBUG
266 if ((QDebug.DebugChannel() & QtDebugChannel.QTDB_TRANSPARENT_PROXY) != 0) {
267 Console.WriteLine( "ENTER InvokeCustomSlot() {0}.{1}",
268 qobj,
269 slotname );
271 #endif
273 MethodInfo slot = Qyoto.GetSlotMethodInfo(qobj.GetType(), slotname);
274 ParameterInfo[] parameters = slot.GetParameters();
275 object[] args = new object[parameters.Length];
277 unsafe {
278 StackItem* stackPtr = (StackItem*) stack;
279 for (int i = 0; i < args.Length; i++) {
280 if (parameters[i].ParameterType == typeof(bool)) {
281 args[i] = stackPtr[i].s_bool;
282 } else if (parameters[i].ParameterType == typeof(sbyte)) {
283 args[i] = stackPtr[i].s_char;
284 } else if (parameters[i].ParameterType == typeof(byte)) {
285 args[i] = stackPtr[i].s_uchar;
286 } else if (parameters[i].ParameterType == typeof(short)) {
287 args[i] = stackPtr[i].s_short;
288 } else if (parameters[i].ParameterType == typeof(ushort)) {
289 args[i] = stackPtr[i].s_ushort;
290 } else if ( parameters[i].ParameterType == typeof(int)
291 || parameters[i].ParameterType.IsEnum )
293 args[i] = stackPtr[i].s_int;
294 } else if (parameters[i].ParameterType == typeof(uint)) {
295 args[i] = stackPtr[i].s_uint;
296 } else if (parameters[i].ParameterType == typeof(long)) {
297 args[i] = stackPtr[i].s_long;
298 } else if (parameters[i].ParameterType == typeof(ulong)) {
299 args[i] = stackPtr[i].s_ulong;
300 } else if (parameters[i].ParameterType == typeof(float)) {
301 args[i] = stackPtr[i].s_float;
302 } else if (parameters[i].ParameterType == typeof(double)) {
303 args[i] = stackPtr[i].s_double;
304 } else if (parameters[i].ParameterType == typeof(string)) {
305 if (stackPtr[i].s_class != IntPtr.Zero) {
306 args[i] = (string) ((GCHandle) stackPtr[i].s_class).Target;
307 #if DEBUG
308 DebugGCHandle.Free((GCHandle) stackPtr[i].s_class);
309 #else
310 ((GCHandle) stackPtr[i].s_class).Free();
311 #endif
313 } else {
314 if (stackPtr[i].s_class != IntPtr.Zero) {
315 args[i] = ((GCHandle) stackPtr[i].s_class).Target;
316 #if DEBUG
317 DebugGCHandle.Free((GCHandle) stackPtr[i].s_class);
318 #else
319 ((GCHandle) stackPtr[i].s_class).Free();
320 #endif
326 object returnValue = slot.Invoke(qobj, args);
327 Type returnType = slot.ReturnType;
329 unsafe {
330 StackItem* retval = (StackItem*) ret;
331 if (returnType == typeof(void)) {
333 } else if (returnType == typeof(bool)) {
334 retval[0].s_bool = (bool) returnValue;
335 } else if (returnType == typeof(sbyte)) {
336 retval[0].s_char = (sbyte) returnValue;
337 } else if (returnType == typeof(byte)) {
338 retval[0].s_uchar = (byte) returnValue;
339 } else if (returnType == typeof(short)) {
340 retval[0].s_short = (short) returnValue;
341 } else if (returnType == typeof(ushort)) {
342 retval[0].s_ushort = (ushort) returnValue;
343 } else if (returnType == typeof(int) || returnType.IsEnum) {
344 retval[0].s_int = (int) returnValue;
345 } else if (returnType == typeof(uint)) {
346 retval[0].s_uint = (uint) returnValue;
347 } else if (returnType == typeof(long)) {
348 retval[0].s_long = (long) returnValue;
349 } else if (returnType == typeof(ulong)) {
350 retval[0].s_ulong = (ulong) returnValue;
351 } else if (returnType == typeof(float)) {
352 retval[0].s_float = (float) returnValue;
353 } else if (returnType == typeof(double)) {
354 retval[0].s_double = (double) returnValue;
355 } else if (returnType == typeof(string)) {
356 #if DEBUG
357 retval[0].s_class = (IntPtr) DebugGCHandle.Alloc(returnValue);
358 #else
359 retval[0].s_class = (IntPtr) GCHandle.Alloc(returnValue);
360 #endif
361 } else if (returnValue == null) {
362 retval[0].s_class = IntPtr.Zero;
363 } else {
364 #if DEBUG
365 retval[0].s_class = (IntPtr) DebugGCHandle.Alloc(returnValue);
366 #else
367 retval[0].s_class = (IntPtr) GCHandle.Alloc(returnValue);
368 #endif
373 static public void InvokeDelegate(Delegate d, IntPtr stack) {
374 unsafe {
375 MethodInfo mi = d.Method;
376 ParameterInfo[] parameters = mi.GetParameters();
377 object[] args = new object[parameters.Length];
378 StackItem* stackPtr = (StackItem*) stack;
379 for (int i = 0; i < args.Length; i++) {
380 if (parameters[i].ParameterType == typeof(bool)) {
381 args[i] = stackPtr[i].s_bool;
382 } else if (parameters[i].ParameterType == typeof(sbyte)) {
383 args[i] = stackPtr[i].s_char;
384 } else if (parameters[i].ParameterType == typeof(byte)) {
385 args[i] = stackPtr[i].s_uchar;
386 } else if (parameters[i].ParameterType == typeof(short)) {
387 args[i] = stackPtr[i].s_short;
388 } else if (parameters[i].ParameterType == typeof(ushort)) {
389 args[i] = stackPtr[i].s_ushort;
390 } else if ( parameters[i].ParameterType == typeof(int)
391 || parameters[i].ParameterType.IsEnum )
393 args[i] = stackPtr[i].s_int;
394 } else if (parameters[i].ParameterType == typeof(uint)) {
395 args[i] = stackPtr[i].s_uint;
396 } else if (parameters[i].ParameterType == typeof(long)) {
397 args[i] = stackPtr[i].s_long;
398 } else if (parameters[i].ParameterType == typeof(ulong)) {
399 args[i] = stackPtr[i].s_ulong;
400 } else if (parameters[i].ParameterType == typeof(float)) {
401 args[i] = stackPtr[i].s_float;
402 } else if (parameters[i].ParameterType == typeof(double)) {
403 args[i] = stackPtr[i].s_double;
404 } else {
405 if (stackPtr[i].s_class != IntPtr.Zero) {
406 args[i] = ((GCHandle) stackPtr[i].s_class).Target;
407 #if DEBUG
408 DebugGCHandle.Free((GCHandle) stackPtr[i].s_class);
409 #else
410 ((GCHandle) stackPtr[i].s_class).Free();
411 #endif
415 d.DynamicInvoke(args);
419 // list of assemblies on which CallInitSmoke() has already been called.
420 public static List<Assembly> InitializedAssemblies = new List<Assembly>();
421 // whether the qyoto (core) runtime has been initialized
422 static bool runtimeInitialized = false;
424 public static void InitRuntime() {
425 if (runtimeInitialized)
426 return;
427 Qyoto.Init_qyoto();
428 SmokeMarshallers.SetUp();
429 // not set when mono is embedded
430 if (AppDomain.CurrentDomain.SetupInformation.ConfigurationFile == null) {
431 PropertyInfo pi = typeof(AppDomain).GetProperty("SetupInformationNoCopy", BindingFlags.NonPublic | BindingFlags.Instance);
432 AppDomainSetup setup = (AppDomainSetup) pi.GetValue(AppDomain.CurrentDomain, null);
433 setup.ConfigurationFile = Assembly.GetExecutingAssembly().Location + ".config";
435 runtimeInitialized = true;
438 public static void TryInitialize(Assembly assembly) {
439 if (InitializedAssemblies.Contains(assembly))
440 return;
441 AssemblySmokeInitializer attr =
442 (AssemblySmokeInitializer) Attribute.GetCustomAttribute(assembly, typeof(AssemblySmokeInitializer));
443 if (attr != null) attr.CallInitSmoke();
444 InitializedAssemblies.Add(assembly);
447 static SmokeInvocation() {
448 InitRuntime();
451 private Type classToProxy;
452 private Object instance;
453 private string className = "";
454 private Dictionary<string, ModuleIndex> methodIdCache;
456 private static Dictionary<Type, Dictionary<string, ModuleIndex>> globalMethodIdCache = new Dictionary<Type, Dictionary<string, ModuleIndex>>();
458 public SmokeInvocation(Type klass, Object obj)
460 classToProxy = klass;
461 instance = obj;
462 className = SmokeMarshallers.SmokeClassName(klass);
464 TryInitialize(klass.Assembly);
466 if (!globalMethodIdCache.TryGetValue(classToProxy, out methodIdCache)) {
467 methodIdCache = new Dictionary<string, ModuleIndex>();
468 globalMethodIdCache[classToProxy] = methodIdCache;
471 if (instance != null) {
472 AddOverridenMethods(instance.GetType());
476 // A variant of Invoke() for use in method calls with 'ref' argument types.
477 // The caller is responsible for setting up the stack, and copying items
478 // back from the stack to the arguments after Invoke() has been called.
479 public void Invoke(string mungedName, string signature, StackItem[] stack) {
480 #if DEBUG
481 if ((QDebug.DebugChannel() & QtDebugChannel.QTDB_TRANSPARENT_PROXY) != 0) {
482 Console.WriteLine( "ENTER SmokeInvocation.Invoke1() MethodName: {0}.{1}",
483 className,
484 signature );
486 #endif
488 ModuleIndex methodId;
489 methodId.smoke = IntPtr.Zero;
490 methodId.index = -1;
491 if (!methodIdCache.TryGetValue(signature, out methodId)) {
492 methodId = FindMethodId(className, mungedName, signature);
494 if (methodId.index == -1) {
495 Console.Error.WriteLine( "LEAVE Invoke() ** Missing method ** {0}.{1}",
496 className,
497 signature );
498 return;
501 methodIdCache[signature] = methodId;
504 unsafe {
505 fixed(StackItem * stackPtr = stack) {
506 if (instance == null) {
507 CallSmokeMethod(methodId.smoke, (int) methodId.index, (IntPtr) 0, (IntPtr) stackPtr, stack.Length);
508 } else {
509 #if DEBUG
510 GCHandle instanceHandle = DebugGCHandle.Alloc(instance);
511 #else
512 GCHandle instanceHandle = GCHandle.Alloc(instance);
513 #endif
514 CallSmokeMethod(methodId.smoke, methodId.index, (IntPtr) instanceHandle, (IntPtr) stackPtr, stack.Length);
515 #if DEBUG
516 DebugGCHandle.Free(instanceHandle);
517 #else
518 instanceHandle.Free();
519 #endif
524 return;
527 public object Invoke(string mungedName, string signature, Type returnType, params object[] args) {
528 #if DEBUG
529 if ((QDebug.DebugChannel() & QtDebugChannel.QTDB_TRANSPARENT_PROXY) != 0) {
530 Console.WriteLine( "ENTER SmokeInvocation.Invoke() MethodName: {0}.{1} Type: {2} ArgCount: {3}",
531 className,
532 signature,
533 returnType,
534 args.Length / 2 );
536 #endif
538 if (signature.StartsWith("operator==")) {
539 if (args[0] == null && args[2] == null)
540 return true;
541 else if (args[0] == null || args[2] == null)
542 return false;
544 ModuleIndex methodId;
545 methodId.smoke = IntPtr.Zero;
546 methodId.index = -1;
547 if (!methodIdCache.TryGetValue(signature, out methodId)) {
548 methodId = FindMethodId(className, mungedName, signature);
550 if (methodId.index == -1) {
551 Console.Error.WriteLine( "LEAVE Invoke() ** Missing method ** {0}.{1}",
552 className,
553 signature );
554 return null;
557 methodIdCache[signature] = methodId;
560 StackItem[] stack = new StackItem[(args.Length / 2) + 1];
562 for (int i = 0, k = 1; i < args.Length; i += 2, k++) {
563 if (args[i+1] == null) {
564 unsafe {
565 stack[k].s_class = IntPtr.Zero;
567 } else if (args[i] == typeof(int) || ((Type) args[i]).IsEnum) {
568 stack[k].s_int = (int) args[i+1];
569 } else if (args[i] == typeof(bool)) {
570 stack[k].s_bool = (bool) args[i+1];
571 } else if (args[i] == typeof(short)) {
572 stack[k].s_short = (short) args[i+1];
573 } else if (args[i] == typeof(float)) {
574 stack[k].s_float = (float) args[i+1];
575 } else if (args[i] == typeof(double)) {
576 stack[k].s_double = (double) args[i+1];
577 } else if (args[i] == typeof(long)) {
578 stack[k].s_long = (long) args[i+1];
579 } else if (args[i] == typeof(ushort)) {
580 stack[k].s_ushort = (ushort) args[i+1];
581 } else if (args[i] == typeof(uint)) {
582 stack[k].s_uint = (uint) args[i+1];
583 } else if (args[i] == typeof(ulong)) {
584 stack[k].s_ulong = (ulong) args[i+1];
585 } else if (args[i] == typeof(sbyte)) {
586 stack[k].s_char = (sbyte) args[i+1];
587 } else if (args[i] == typeof(byte)) {
588 stack[k].s_uchar = (byte) args[i+1];
589 } else {
590 #if DEBUG
591 stack[k].s_class = (IntPtr) DebugGCHandle.Alloc(args[i+1]);
592 #else
593 stack[k].s_class = (IntPtr) GCHandle.Alloc(args[i+1]);
594 #endif
598 object returnValue = null;
600 unsafe {
601 fixed(StackItem * stackPtr = stack) {
602 if (instance == null) {
603 CallSmokeMethod(methodId.smoke, (int) methodId.index, (IntPtr) 0, (IntPtr) stackPtr, args.Length / 2);
604 } else {
605 #if DEBUG
606 GCHandle instanceHandle = DebugGCHandle.Alloc(instance);
607 #else
608 GCHandle instanceHandle = GCHandle.Alloc(instance);
609 #endif
610 CallSmokeMethod(methodId.smoke, methodId.index, (IntPtr) instanceHandle, (IntPtr) stackPtr, args.Length / 2);
611 #if DEBUG
612 DebugGCHandle.Free(instanceHandle);
613 #else
614 instanceHandle.Free();
615 #endif
618 if (returnType == typeof(void)) {
620 } else if (returnType == typeof(int)) {
621 returnValue = stack[0].s_int;
622 } else if (returnType == typeof(bool)) {
623 returnValue = stack[0].s_bool;
624 } else if (returnType == typeof(short)) {
625 returnValue = stack[0].s_short;
626 } else if (returnType == typeof(float)) {
627 returnValue = stack[0].s_float;
628 } else if (returnType == typeof(double)) {
629 returnValue = stack[0].s_double;
630 } else if (returnType == typeof(long)) {
631 returnValue = stack[0].s_long;
632 } else if (returnType == typeof(ushort)) {
633 returnValue = stack[0].s_ushort;
634 } else if (returnType == typeof(uint)) {
635 returnValue = stack[0].s_uint;
636 } else if (returnType.IsEnum) {
637 returnValue = Enum.ToObject(returnType, stack[0].s_int);
638 } else if (returnType == typeof(ulong)) {
639 returnValue = stack[0].s_ulong;
640 } else if (returnType == typeof(sbyte)) {
641 returnValue = stack[0].s_char;
642 } else if (returnType == typeof(byte)) {
643 returnValue = stack[0].s_uchar;
644 } else if (returnType == typeof(char)) {
645 returnValue = (char) stack[0].s_char;
646 } else {
647 if (((IntPtr) stack[0].s_class) == IntPtr.Zero) {
648 returnValue = null;
649 } else {
650 returnValue = ((GCHandle) stack[0].s_class).Target;
651 #if DEBUG
652 DebugGCHandle.Free((GCHandle) stack[0].s_class);
653 #else
654 ((GCHandle) stack[0].s_class).Free();
655 #endif
661 return returnValue;
664 public override int GetHashCode() {
665 #if DEBUG
666 return QyotoHash((IntPtr) DebugGCHandle.Alloc(instance));
667 #else
668 return QyotoHash((IntPtr) GCHandle.Alloc(instance));
669 #endif
673 public class SignalInvocation : RealProxy {
674 [DllImport("libqyoto", CharSet=CharSet.Ansi)]
675 static extern bool SignalEmit(string signature, string type, IntPtr target, IntPtr sp, int items);
677 private Type signalsInterface;
678 private Object instance;
680 public SignalInvocation(Type iface, Object obj) : base(iface)
682 signalsInterface = iface;
683 instance = obj;
686 public override IMessage Invoke(IMessage message) {
687 IMethodCallMessage callMessage = (IMethodCallMessage) message;
688 StackItem[] stack = new StackItem[callMessage.ArgCount+1];
690 #if DEBUG
691 if ((QDebug.DebugChannel() & QtDebugChannel.QTDB_TRANSPARENT_PROXY) != 0) {
692 Console.WriteLine( "ENTER SignalInvocation.Invoke() MethodName: {0}.{1} Type: {2} ArgCount: {3}",
693 instance,
694 callMessage.MethodName,
695 callMessage.TypeName,
696 callMessage.ArgCount.ToString() );
698 #endif
700 if (callMessage.MethodSignature != null) {
701 Type[] types = (Type[]) callMessage.MethodSignature;
703 for (int i = 0; i < callMessage.ArgCount; i++) {
704 if (callMessage.Args[i] == null) {
705 unsafe {
706 stack[i + 1].s_class = (IntPtr) 0;
708 } else if (types[i] == typeof(bool)) {
709 stack[i + 1].s_bool = (bool) callMessage.Args[i];
710 } else if (types[i] == typeof(sbyte)) {
711 stack[i + 1].s_char = (sbyte) callMessage.Args[i];
712 } else if (types[i] == typeof(byte)) {
713 stack[i + 1].s_uchar = (byte) callMessage.Args[i];
714 } else if (types[i] == typeof(short)) {
715 stack[i + 1].s_short = (short) callMessage.Args[i];
716 } else if (types[i] == typeof(ushort)) {
717 stack[i + 1].s_ushort = (ushort) callMessage.Args[i];
718 } else if (types[i] == typeof(int) || types[i].IsEnum) {
719 stack[i + 1].s_int = (int) callMessage.Args[i];
720 } else if (types[i] == typeof(uint)) {
721 stack[i + 1].s_uint = (uint) callMessage.Args[i];
722 } else if (types[i] == typeof(long)) {
723 stack[i + 1].s_long = (long) callMessage.Args[i];
724 } else if (types[i] == typeof(ulong)) {
725 stack[i + 1].s_ulong = (ulong) callMessage.Args[i];
726 } else if (types[i] == typeof(float)) {
727 stack[i + 1].s_float = (float) callMessage.Args[i];
728 } else if (types[i] == typeof(double)) {
729 stack[i + 1].s_double = (double) callMessage.Args[i];
730 } else if (types[i] == typeof(string)) {
731 #if DEBUG
732 stack[i + 1].s_class = (IntPtr) DebugGCHandle.Alloc(callMessage.Args[i]);
733 #else
734 stack[i + 1].s_class = (IntPtr) GCHandle.Alloc(callMessage.Args[i]);
735 #endif
736 } else {
737 #if DEBUG
738 stack[i + 1].s_class = (IntPtr) DebugGCHandle.Alloc(callMessage.Args[i]);
739 #else
740 stack[i + 1].s_class = (IntPtr) GCHandle.Alloc(callMessage.Args[i]);
741 #endif
746 IMethodReturnMessage returnMessage = (IMethodReturnMessage) message;
747 MethodReturnMessageWrapper returnValue = new MethodReturnMessageWrapper((IMethodReturnMessage) returnMessage);
749 #if DEBUG
750 GCHandle instanceHandle = DebugGCHandle.Alloc(instance);
751 #else
752 GCHandle instanceHandle = GCHandle.Alloc(instance);
753 #endif
755 Qyoto.CPPMethod signalEntry = Qyoto.GetSignalSignature(signalsInterface, (MethodInfo) callMessage.MethodBase);
757 unsafe {
758 fixed(StackItem * stackPtr = stack) {
759 Type returnType = ((MethodInfo) returnMessage.MethodBase).ReturnType;
760 SignalEmit(signalEntry.signature, signalEntry.type, (IntPtr) instanceHandle, (IntPtr) stackPtr, callMessage.ArgCount);
762 if (returnType == typeof(void)) {
764 } else if (returnType == typeof(bool)) {
765 returnValue.ReturnValue = stack[0].s_bool;
766 } else if (returnType == typeof(sbyte)) {
767 returnValue.ReturnValue = stack[0].s_char;
768 } else if (returnType == typeof(byte)) {
769 returnValue.ReturnValue = stack[0].s_uchar;
770 } else if (returnType == typeof(short)) {
771 returnValue.ReturnValue = stack[0].s_short;
772 } else if (returnType == typeof(ushort)) {
773 returnValue.ReturnValue = stack[0].s_ushort;
774 } else if (returnType.IsEnum) {
775 returnValue.ReturnValue = Enum.ToObject(returnType, stack[0].s_int);
776 } else if (returnType == typeof(int)) {
777 returnValue.ReturnValue = stack[0].s_int;
778 } else if (returnType == typeof(uint)) {
779 returnValue.ReturnValue = stack[0].s_uint;
780 } else if (returnType == typeof(long)) {
781 returnValue.ReturnValue = stack[0].s_long;
782 } else if (returnType == typeof(ulong)) {
783 returnValue.ReturnValue = stack[0].s_ulong;
784 } else if (returnType == typeof(float)) {
785 returnValue.ReturnValue = stack[0].s_float;
786 } else if (returnType == typeof(double)) {
787 returnValue.ReturnValue = stack[0].s_double;
788 } else if (returnType == typeof(string)) {
789 if (stack[0].s_class != IntPtr.Zero) {
790 returnValue.ReturnValue = ((GCHandle) stack[0].s_class).Target;
791 #if DEBUG
792 DebugGCHandle.Free((GCHandle) stack[0].s_class);
793 #else
794 ((GCHandle) stack[0].s_class).Free();
795 #endif
798 } else {
799 if (stack[0].s_class != IntPtr.Zero) {
800 returnValue.ReturnValue = ((GCHandle) stack[0].s_class).Target;
801 #if DEBUG
802 DebugGCHandle.Free((GCHandle) stack[0].s_class);
803 #else
804 ((GCHandle) stack[0].s_class).Free();
805 #endif
811 returnMessage = returnValue;
812 return returnMessage;
815 public override int GetHashCode() {
816 return instance.GetHashCode();