1 /***************************************************************************
2 SmokeInvocation.cs - description
4 begin : Wed Jun 16 2004
5 copyright : (C) 2004 by Richard Dale
6 email : richard.j.dale@gmail.com
7 ***************************************************************************/
9 /***************************************************************************
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. *
16 ***************************************************************************/
20 using System
.Collections
;
21 using System
.Collections
.Generic
;
22 using System
.Diagnostics
;
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
{
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
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
)) {
77 if (overridenMethods
.ContainsKey(klass
))
80 Dictionary
<string, MemberInfo
> methodsHash
= new Dictionary
<string, MemberInfo
>();
81 overridenMethods
.Add(klass
, methodsHash
);
84 MemberInfo
[] methods
= klass
.FindMembers( MemberTypes
.Method
,
86 | BindingFlags
.NonPublic
87 | BindingFlags
.Instance
88 | BindingFlags
.DeclaredOnly
,
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
,
97 | BindingFlags
.NonPublic
98 | BindingFlags
.Instance
99 | BindingFlags
.DeclaredOnly
,
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") {
129 return (IntPtr
) DebugGCHandle
.Alloc(metaObjectMethod
);
131 return (IntPtr
) GCHandle
.Alloc(metaObjectMethod
);
135 Dictionary
<string, MemberInfo
> methods
;
136 if (!overridenMethods
.TryGetValue(klass
, out methods
)) {
140 MemberInfo methodInfo
;
141 if (!methods
.TryGetValue(method
, out methodInfo
)) {
146 return (IntPtr
) DebugGCHandle
.Alloc(methodInfo
);
148 return (IntPtr
) GCHandle
.Alloc(methodInfo
);
152 public static void InvokeMethod(IntPtr instanceHandle
, IntPtr methodHandle
, IntPtr stack
) {
153 object instance
= ((GCHandle
) instanceHandle
).Target
;
154 MethodInfo method
= (MethodInfo
) ((GCHandle
) methodHandle
).Target
;
156 if ( (QDebug
.DebugChannel() & QtDebugChannel
.QTDB_TRANSPARENT_PROXY
) != 0
157 && (QDebug
.DebugChannel() & QtDebugChannel
.QTDB_VIRTUAL
) != 0 )
159 Console
.WriteLine( "ENTER InvokeMethod() {0}.{1}",
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
;
199 DebugGCHandle
.Free((GCHandle
) stackPtr
[i
+1].s_class
);
201 ((GCHandle
) stackPtr
[i
+1].s_class
).Free();
205 if (stackPtr
[i
+1].s_class
!= IntPtr
.Zero
) {
206 args
[i
] = ((GCHandle
) stackPtr
[i
+1].s_class
).Target
;
208 DebugGCHandle
.Free((GCHandle
) stackPtr
[i
+1].s_class
);
210 ((GCHandle
) stackPtr
[i
+1].s_class
).Free();
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)) {
245 stackPtr
[0].s_class
= (IntPtr
) DebugGCHandle
.Alloc(returnValue
);
247 stackPtr
[0].s_class
= (IntPtr
) GCHandle
.Alloc(returnValue
);
249 } else if (returnValue
== null) {
250 stackPtr
[0].s_class
= IntPtr
.Zero
;
253 stackPtr
[0].s_class
= (IntPtr
) DebugGCHandle
.Alloc(returnValue
);
255 stackPtr
[0].s_class
= (IntPtr
) GCHandle
.Alloc(returnValue
);
263 static public void InvokeCustomSlot(IntPtr obj
, string slotname
, IntPtr stack
, IntPtr ret
) {
264 QObject qobj
= (QObject
) ((GCHandle
)obj
).Target
;
266 if ((QDebug
.DebugChannel() & QtDebugChannel
.QTDB_TRANSPARENT_PROXY
) != 0) {
267 Console
.WriteLine( "ENTER InvokeCustomSlot() {0}.{1}",
273 MethodInfo slot
= Qyoto
.GetSlotMethodInfo(qobj
.GetType(), slotname
);
274 ParameterInfo
[] parameters
= slot
.GetParameters();
275 object[] args
= new object[parameters
.Length
];
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
;
308 DebugGCHandle
.Free((GCHandle
) stackPtr
[i
].s_class
);
310 ((GCHandle
) stackPtr
[i
].s_class
).Free();
314 if (stackPtr
[i
].s_class
!= IntPtr
.Zero
) {
315 args
[i
] = ((GCHandle
) stackPtr
[i
].s_class
).Target
;
317 DebugGCHandle
.Free((GCHandle
) stackPtr
[i
].s_class
);
319 ((GCHandle
) stackPtr
[i
].s_class
).Free();
326 object returnValue
= slot
.Invoke(qobj
, args
);
327 Type returnType
= slot
.ReturnType
;
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)) {
357 retval
[0].s_class
= (IntPtr
) DebugGCHandle
.Alloc(returnValue
);
359 retval
[0].s_class
= (IntPtr
) GCHandle
.Alloc(returnValue
);
361 } else if (returnValue
== null) {
362 retval
[0].s_class
= IntPtr
.Zero
;
365 retval
[0].s_class
= (IntPtr
) DebugGCHandle
.Alloc(returnValue
);
367 retval
[0].s_class
= (IntPtr
) GCHandle
.Alloc(returnValue
);
373 static public void InvokeDelegate(Delegate d
, IntPtr stack
) {
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
;
405 if (stackPtr
[i
].s_class
!= IntPtr
.Zero
) {
406 args
[i
] = ((GCHandle
) stackPtr
[i
].s_class
).Target
;
408 DebugGCHandle
.Free((GCHandle
) stackPtr
[i
].s_class
);
410 ((GCHandle
) stackPtr
[i
].s_class
).Free();
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
)
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
))
441 AssemblySmokeInitializer attr
=
442 (AssemblySmokeInitializer
) Attribute
.GetCustomAttribute(assembly
, typeof(AssemblySmokeInitializer
));
443 if (attr
!= null) attr
.CallInitSmoke();
444 InitializedAssemblies
.Add(assembly
);
447 static SmokeInvocation() {
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
;
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
) {
481 if ((QDebug
.DebugChannel() & QtDebugChannel
.QTDB_TRANSPARENT_PROXY
) != 0) {
482 Console
.WriteLine( "ENTER SmokeInvocation.Invoke1() MethodName: {0}.{1}",
488 ModuleIndex methodId
;
489 methodId
.smoke
= IntPtr
.Zero
;
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}",
501 methodIdCache
[signature
] = methodId
;
505 fixed(StackItem
* stackPtr
= stack
) {
506 if (instance
== null) {
507 CallSmokeMethod(methodId
.smoke
, (int) methodId
.index
, (IntPtr
) 0, (IntPtr
) stackPtr
, stack
.Length
);
510 GCHandle instanceHandle
= DebugGCHandle
.Alloc(instance
);
512 GCHandle instanceHandle
= GCHandle
.Alloc(instance
);
514 CallSmokeMethod(methodId
.smoke
, methodId
.index
, (IntPtr
) instanceHandle
, (IntPtr
) stackPtr
, stack
.Length
);
516 DebugGCHandle
.Free(instanceHandle
);
518 instanceHandle
.Free();
527 public object Invoke(string mungedName
, string signature
, Type returnType
, params object[] args
) {
529 if ((QDebug
.DebugChannel() & QtDebugChannel
.QTDB_TRANSPARENT_PROXY
) != 0) {
530 Console
.WriteLine( "ENTER SmokeInvocation.Invoke() MethodName: {0}.{1} Type: {2} ArgCount: {3}",
538 if (signature
.StartsWith("operator==")) {
539 if (args
[0] == null && args
[2] == null)
541 else if (args
[0] == null || args
[2] == null)
544 ModuleIndex methodId
;
545 methodId
.smoke
= IntPtr
.Zero
;
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}",
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) {
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];
591 stack
[k
].s_class
= (IntPtr
) DebugGCHandle
.Alloc(args
[i
+1]);
593 stack
[k
].s_class
= (IntPtr
) GCHandle
.Alloc(args
[i
+1]);
598 object returnValue
= null;
601 fixed(StackItem
* stackPtr
= stack
) {
602 if (instance
== null) {
603 CallSmokeMethod(methodId
.smoke
, (int) methodId
.index
, (IntPtr
) 0, (IntPtr
) stackPtr
, args
.Length
/ 2);
606 GCHandle instanceHandle
= DebugGCHandle
.Alloc(instance
);
608 GCHandle instanceHandle
= GCHandle
.Alloc(instance
);
610 CallSmokeMethod(methodId
.smoke
, methodId
.index
, (IntPtr
) instanceHandle
, (IntPtr
) stackPtr
, args
.Length
/ 2);
612 DebugGCHandle
.Free(instanceHandle
);
614 instanceHandle
.Free();
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
;
647 if (((IntPtr
) stack
[0].s_class
) == IntPtr
.Zero
) {
650 returnValue
= ((GCHandle
) stack
[0].s_class
).Target
;
652 DebugGCHandle
.Free((GCHandle
) stack
[0].s_class
);
654 ((GCHandle
) stack
[0].s_class
).Free();
664 public override int GetHashCode() {
666 return QyotoHash((IntPtr
) DebugGCHandle
.Alloc(instance
));
668 return QyotoHash((IntPtr
) GCHandle
.Alloc(instance
));
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
;
686 public override IMessage
Invoke(IMessage message
) {
687 IMethodCallMessage callMessage
= (IMethodCallMessage
) message
;
688 StackItem
[] stack
= new StackItem
[callMessage
.ArgCount
+1];
691 if ((QDebug
.DebugChannel() & QtDebugChannel
.QTDB_TRANSPARENT_PROXY
) != 0) {
692 Console
.WriteLine( "ENTER SignalInvocation.Invoke() MethodName: {0}.{1} Type: {2} ArgCount: {3}",
694 callMessage
.MethodName
,
695 callMessage
.TypeName
,
696 callMessage
.ArgCount
.ToString() );
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) {
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)) {
732 stack
[i
+ 1].s_class
= (IntPtr
) DebugGCHandle
.Alloc(callMessage
.Args
[i
]);
734 stack
[i
+ 1].s_class
= (IntPtr
) GCHandle
.Alloc(callMessage
.Args
[i
]);
738 stack
[i
+ 1].s_class
= (IntPtr
) DebugGCHandle
.Alloc(callMessage
.Args
[i
]);
740 stack
[i
+ 1].s_class
= (IntPtr
) GCHandle
.Alloc(callMessage
.Args
[i
]);
746 IMethodReturnMessage returnMessage
= (IMethodReturnMessage
) message
;
747 MethodReturnMessageWrapper returnValue
= new MethodReturnMessageWrapper((IMethodReturnMessage
) returnMessage
);
750 GCHandle instanceHandle
= DebugGCHandle
.Alloc(instance
);
752 GCHandle instanceHandle
= GCHandle
.Alloc(instance
);
755 Qyoto
.CPPMethod signalEntry
= Qyoto
.GetSignalSignature(signalsInterface
, (MethodInfo
) callMessage
.MethodBase
);
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
;
792 DebugGCHandle
.Free((GCHandle
) stack
[0].s_class
);
794 ((GCHandle
) stack
[0].s_class
).Free();
799 if (stack
[0].s_class
!= IntPtr
.Zero
) {
800 returnValue
.ReturnValue
= ((GCHandle
) stack
[0].s_class
).Target
;
802 DebugGCHandle
.Free((GCHandle
) stack
[0].s_class
);
804 ((GCHandle
) stack
[0].s_class
).Free();
811 returnMessage
= returnValue
;
812 return returnMessage
;
815 public override int GetHashCode() {
816 return instance
.GetHashCode();