private static IntPtr ImplementStaticMethod (IntPtr cls, IntPtr sel, VarargStack stack) { try { if (!ClassesRegistered.Contains (cls)) return IntPtr.Zero; ArrayList arguments = new ArrayList (); Type type = (Type) ClassesRegistered [cls]; string selector = Marshal.PtrToStringAuto (sel); Type [] argumentTypes = ArgumentTypesForCall (class_getClassMethod (cls, sel)); MethodInfo method = type.GetMethod (SelectorToMethod (selector, type), BindingFlags.Static | BindingFlags.Public, null, argumentTypes, null); unsafe { int argptr = (int)&sel+4; foreach (ParameterInfo parameter in method.GetParameters ()) { if (parameter.ParameterType.IsPrimitive || parameter.ParameterType.IsValueType) { arguments.Add (Marshal.PtrToStructure ((IntPtr)argptr, parameter.ParameterType)); } else { if (parameter.ParameterType == typeof (string)) arguments.Add (Marshal.PtrToStringAuto (Marshal.ReadIntPtr ((IntPtr)argptr))); else { IntPtr objectptr = Marshal.ReadIntPtr ((IntPtr)argptr); if (ManagedInstances.Contains (objectptr)) arguments.Add (ManagedInstances [objectptr]); else { IntPtr objccls = (IntPtr) ObjCMessaging.objc_msgSend (objectptr, "class", typeof (IntPtr)); if (!NativeClasses.Contains (objccls)) NativeClasses [objccls] = AddTypeForClass ((string) ObjCMessaging.objc_msgSend ((IntPtr) ObjCMessaging.objc_msgSend (objccls, "className", typeof (IntPtr)), "cString", typeof (string))); object o = ((Type) NativeClasses [objccls]).GetConstructor (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new Type [] { typeof (IntPtr) }, null).Invoke (new object [] { objectptr }); ManagedInstances [objectptr] = o; NativeInstances [o] = objectptr; arguments.Add (o); } } } argptr += Marshal.SizeOf (typeof (IntPtr)); } } object return_value = type.InvokeMember (SelectorToMethod (selector, type), BindingFlags.Static | BindingFlags.InvokeMethod, null, null, (object [])arguments.ToArray (typeof (object))); return ManagedToNative (return_value); } catch (TargetInvocationException e) { IntPtr nsex = objc_getClass ("NSException"); IntPtr nsstr = objc_getClass ("NSString"); IntPtr nm = (IntPtr) ObjCMessaging.objc_msgSend (nsstr, "stringWithUTF8String:", typeof (IntPtr), typeof (string), e.InnerException.GetType ().ToString ()); IntPtr rsn = (IntPtr) ObjCMessaging.objc_msgSend (nsstr, "stringWithUTF8String:", typeof (IntPtr), typeof (string), e.InnerException.ToString ()); IntPtr ex = (IntPtr) ObjCMessaging.objc_msgSend (nsex, "exceptionWithName:reason:userInfo:", typeof (IntPtr), typeof (IntPtr), nm, typeof (IntPtr), rsn, typeof (IntPtr), IntPtr.Zero); ObjCMessaging.objc_msgSend (ex, "raise", typeof (void)); throw new Exception ("ImplementMethod post NSException should never be reached"); } catch (Exception e) { IntPtr nsex = objc_getClass ("NSException"); IntPtr nsstr = objc_getClass ("NSString"); IntPtr nm = (IntPtr) ObjCMessaging.objc_msgSend (nsstr, "stringWithUTF8String:", typeof (IntPtr), typeof (string), e.GetType ().ToString ()); IntPtr rsn = (IntPtr) ObjCMessaging.objc_msgSend (nsstr, "stringWithUTF8String:", typeof (IntPtr), typeof (string), e.ToString ()); IntPtr ex = (IntPtr) ObjCMessaging.objc_msgSend (nsex, "exceptionWithName:reason:userInfo:", typeof (IntPtr), typeof (IntPtr), nm, typeof (IntPtr), rsn, typeof (IntPtr), IntPtr.Zero); ObjCMessaging.objc_msgSend (ex, "raise", typeof (void)); throw new Exception ("ImplementMethod post NSException should never be reached"); } }
private static IntPtr ConstructObject (IntPtr cls, IntPtr sel, VarargStack stack) { if (!ClassesRegistered.Contains (cls)) return IntPtr.Zero; ArrayList arguments = new ArrayList (); Type type = (Type) ClassesRegistered [cls]; Type [] argumentTypes = ArgumentTypesForCall (class_getClassMethod (cls, sel)); if (argumentTypes.Length == 0) argumentTypes = new Type [0]; ConstructorInfo constructor = type.GetConstructor (BindingFlags.Instance | BindingFlags.Public, null, argumentTypes, null); unsafe { int argptr = (int)&sel+4; foreach (ParameterInfo parameter in constructor.GetParameters ()) { if (parameter.ParameterType.IsPrimitive || parameter.ParameterType.IsValueType) { if (type.IsSubclassOf (typeof (Delegate)) && parameter.ParameterType == typeof (IntPtr)) { // This is a magic case; we know that the target is on arguments [0]; object target = arguments [0]; string selector = Marshal.PtrToStringAuto (Marshal.ReadIntPtr ((IntPtr)argptr)); MethodInfo target_method = target.GetType ().GetMethod (SelectorToMethod (selector, target.GetType ())); arguments.Add (MethodInfoToFtnptr (target_method)); } else arguments.Add (Marshal.PtrToStructure ((IntPtr)argptr, parameter.ParameterType)); } else { if (parameter.ParameterType == typeof (string)) arguments.Add (Marshal.PtrToStringAuto (Marshal.ReadIntPtr ((IntPtr)argptr))); else { IntPtr objectptr = Marshal.ReadIntPtr ((IntPtr)argptr); if (ManagedInstances.Contains (objectptr)) arguments.Add (ManagedInstances [objectptr]); else { IntPtr objccls = (IntPtr) ObjCMessaging.objc_msgSend (objectptr, "class", typeof (IntPtr)); if (!NativeClasses.Contains (objccls)) NativeClasses [objccls] = AddTypeForClass ((string) ObjCMessaging.objc_msgSend ((IntPtr) ObjCMessaging.objc_msgSend (objccls, "className", typeof (IntPtr)), "cString", typeof (string))); object o = ((Type) NativeClasses [objccls]).GetConstructor (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new Type [] { typeof (IntPtr) }, null).Invoke (new object [] { objectptr }); ManagedInstances [objectptr] = o; NativeInstances [o] = objectptr; arguments.Add (o); } } } argptr += Marshal.SizeOf (typeof (IntPtr)); } } object return_value = constructor.Invoke ((object [])arguments.ToArray (typeof (object))); IntPtr native_object = (IntPtr) ObjCMessaging.objc_msgSend (cls, "alloc", typeof (IntPtr)); ManagedInstances [native_object] = return_value; NativeInstances [return_value] = native_object; return native_object; }