private static objc_class RootClass(objc_class super_class) { objc_class root_class = super_class; while (root_class.super_class != IntPtr.Zero) { root_class = (objc_class)Marshal.PtrToStructure(root_class.super_class, typeof(objc_class)); } return(root_class); }
public ObjCClass(objc_class native_class, IntPtr native_pointer) { this.native_class = native_class; this.native_pointer = native_pointer; }
public static ObjCClass FromType(Type type) { if (type == null) { throw new ArgumentException(); } if (objc_classes [type] != null) { return((ObjCClass)objc_classes [type]); } FieldInfo class_name = type.GetField("ObjectiveCName", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); FieldInfo base_name = type.BaseType.GetField("ObjectiveCName", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); string cls_name = type.Name; string super_name = type.BaseType.Name; if (class_name != null) { cls_name = (string)class_name.GetValue(type); } RegisterAttribute attr = (RegisterAttribute)Attribute.GetCustomAttribute(type, typeof(RegisterAttribute)); if (attr != null) { cls_name = attr.Name; } IntPtr this_ptr = ObjCMethods.objc_lookUpClass(cls_name); if (this_ptr != IntPtr.Zero) { return(new ObjCClass((objc_class)Marshal.PtrToStructure(this_ptr, typeof(objc_class)), this_ptr)); } if (base_name != null) { super_name = (string)base_name.GetValue(type.BaseType); } if (super_name == "CSObject" || super_name == "Object") { super_name = "NSObject"; } if (cls_name == "CSThread") { super_name = "NSThread"; } IntPtr super_ptr = ObjCMethods.objc_getClass(super_name); if (super_ptr == IntPtr.Zero) { return(null); } objc_class super_class = (objc_class)Marshal.PtrToStructure(super_ptr, typeof(objc_class)); objc_class root_class = RootClass(super_class); objc_class objc_class = new objc_class(); objc_class meta_class = new objc_class(); // setup the meta class meta_class.isa = root_class.isa; meta_class.super_class = super_class.isa; meta_class.instance_size = ((objc_class)Marshal.PtrToStructure(super_class.isa, typeof(objc_class))).instance_size; meta_class.name = Marshal.StringToHGlobalAnsi(cls_name); meta_class.info = 2; meta_class.methodLists = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr))); Marshal.WriteIntPtr(meta_class.methodLists, (IntPtr)(-1)); IntPtr meta_class_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(objc_class)); Marshal.StructureToPtr(meta_class, meta_class_ptr, true); // setup the class objc_class.isa = meta_class_ptr; objc_class.name = meta_class.name; objc_class.info = 1; objc_class.super_class = super_ptr; objc_class.methodLists = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr))); Marshal.WriteIntPtr(objc_class.methodLists, (IntPtr)(-1)); // Add the ivars ArrayList ivars = new ArrayList(); foreach (FieldInfo field in type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { ConnectAttribute cattr = (ConnectAttribute)Attribute.GetCustomAttribute(field, typeof(ConnectAttribute)); if (cattr != null) { ivars.Add(field); } } if (ivars.Count > 0) { objc_ivar_list ivar_list = new objc_ivar_list(); ivar_list.count = ivars.Count; IntPtr ivar_list_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(objc_ivar_list)) + (ivars.Count * Marshal.SizeOf(typeof(objc_method)))); int ivar_offset = super_class.instance_size; for (int i = 0; i < ivars.Count; i++) { ConnectAttribute cattr = (ConnectAttribute)Attribute.GetCustomAttribute((FieldInfo)ivars [i], typeof(ConnectAttribute)); objc_ivar ivar = new objc_ivar(); int ivar_size = cattr.Size; ivar.ivar_name = Marshal.StringToHGlobalAnsi(cattr.Name != null ? cattr.Name : ((FieldInfo)ivars [i]).Name); ivar.ivar_type = Marshal.StringToHGlobalAnsi(cattr.Type != null ? cattr.Type : ObjCTypes.FromType(((FieldInfo)ivars [i]).FieldType, out ivar_size)); ivar.ivar_offset = ivar_offset; ivar_offset += ivar_size; Marshal.StructureToPtr(ivar, (IntPtr)((long)ivar_list_ptr + Marshal.SizeOf(typeof(objc_ivar_list)) + (i * Marshal.SizeOf(typeof(objc_ivar)))), true); } Marshal.StructureToPtr(ivar_list, ivar_list_ptr, false); objc_class.instance_size = ivar_offset; objc_class.ivars = ivar_list_ptr; } else { objc_class.instance_size = super_class.instance_size; } // Register the class IntPtr objc_class_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(objc_class)); Marshal.StructureToPtr(objc_class, objc_class_ptr, true); ObjCMethods.objc_addClass(objc_class_ptr); // Add the methods objc_method_list method_list = new objc_method_list(); ArrayList methods = new ArrayList(); foreach (MethodInfo method in type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { if (type.Namespace != "Cocoa") { ExportAttribute eattr = (ExportAttribute)Attribute.GetCustomAttribute(method, typeof(ExportAttribute)); if (eattr != null) { methods.Add(ObjCMethod.FromMethodInfo(method)); } } else { methods.Add(ObjCMethod.FromMethodInfo(method)); } } // FIXME // foreach (ConstructorInfo constructor in type.GetConstructors (BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance)) // methods.Add (ObjCMethod.FromConstructorInfo (constructor)); method_list.count = methods.Count; IntPtr method_list_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(objc_method_list)) + (methods.Count * Marshal.SizeOf(typeof(objc_method)))); Marshal.StructureToPtr(method_list, method_list_ptr, false); for (int i = 0; i < methods.Count; i++) { Marshal.StructureToPtr((objc_method)methods [i], (IntPtr)((long)method_list_ptr + Marshal.SizeOf(typeof(objc_method_list)) + (i * Marshal.SizeOf(typeof(objc_method)))), true); } ObjCMethods.class_addMethods(objc_class_ptr, method_list_ptr); // Add the static methods method_list = new objc_method_list(); methods = new ArrayList(); foreach (MethodInfo method in type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)) { if (type.Namespace != "Cocoa") { ExportAttribute eattr = (ExportAttribute)Attribute.GetCustomAttribute(method, typeof(ExportAttribute)); if (eattr != null) { methods.Add(ObjCMethod.FromMethodInfo(method)); } } else { methods.Add(ObjCMethod.FromMethodInfo(method)); } } method_list.count = methods.Count; IntPtr static_method_list_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(objc_method_list)) + (methods.Count * Marshal.SizeOf(typeof(objc_method)))); Marshal.StructureToPtr(method_list, static_method_list_ptr, false); for (int i = 0; i < methods.Count; i++) { Marshal.StructureToPtr((objc_method)methods [i], (IntPtr)((long)static_method_list_ptr + Marshal.SizeOf(typeof(objc_method_list)) + (i * Marshal.SizeOf(typeof(objc_method)))), true); } ObjCMethods.class_addMethods(meta_class_ptr, static_method_list_ptr); return(new ObjCClass(objc_class, objc_class_ptr)); }