78
78
return Marshal.PtrToStringAuto (ptr);
82
internal static string GetName (IntPtr @class)
84
return Marshal.PtrToStringAuto (class_getName (@class));
82
87
public static IntPtr GetHandle (string name) {
83
88
return objc_getClass (name);
91
public static IntPtr GetHandle (Type type) {
92
RegisterAttribute attr = (RegisterAttribute) Attribute.GetCustomAttribute (type, typeof (RegisterAttribute), false);
93
string name = attr == null ? type.FullName : attr.Name ?? type.FullName;
94
bool is_wrapper = attr == null ? false : attr.IsWrapper;
95
var handle = objc_getClass (name);
97
if (handle == IntPtr.Zero)
98
handle = Class.Register (type, name, is_wrapper);
86
103
public static bool IsCustomType (Type type) {
87
return custom_types.Contains (type);
90
internal static Type Lookup (IntPtr klass) {
105
return custom_types.ContainsKey (type);
108
internal static Type Lookup (IntPtr klass)
110
return Lookup (klass, true);
113
internal static Type Lookup (IntPtr klass, bool throw_on_error) {
93
if (type_map.TryGetValue (klass, out type))
96
// TODO: When we type walk we currently populate the type map
97
// from the walk point with the target, we should gather some
98
// stats here, and see how many times there is a intermediate class
99
// and see if we should populate them in the map as well
100
IntPtr orig_klass = klass;
103
IntPtr kls = class_getSuperclass (klass);
105
if (type_map.TryGetValue (kls, out type)) {
106
type_map [orig_klass] = type;
117
if (type_map.TryGetValue (klass, out type))
120
// TODO: When we type walk we currently populate the type map
121
// from the walk point with the target, we should gather some
122
// stats here, and see how many times there is a intermediate class
123
// and see if we should populate them in the map as well
124
IntPtr orig_klass = klass;
127
IntPtr kls = class_getSuperclass (klass);
129
if (type_map.TryGetValue (kls, out type)) {
130
type_map [orig_klass] = type;
134
if (kls == IntPtr.Zero) {
138
var message = "Could not find a valid superclass for type " + new Class (orig_klass).Name
139
+ ". Did you forget to register the bindings at " + typeof(Class).FullName
140
+ ".Register() or call NSApplication.Init()?";
141
throw new ArgumentException (message);
114
149
internal static IntPtr Register (Type type) {
115
150
RegisterAttribute attr = (RegisterAttribute) Attribute.GetCustomAttribute (type, typeof (RegisterAttribute), false);
116
151
string name = attr == null ? type.FullName : attr.Name ?? type.FullName;
117
return Class.Register (type, name);
152
bool is_wrapper = attr == null ? false : attr.IsWrapper;
153
return Register (type, name, is_wrapper);
120
internal unsafe static IntPtr Register (Type type, string name) {
156
static IntPtr Register (Type type, string name, bool is_wrapper) {
121
157
IntPtr parent = IntPtr.Zero;
122
158
IntPtr handle = IntPtr.Zero;
124
160
handle = objc_getClass (name);
126
if (handle != IntPtr.Zero) {
127
if (!type_map.ContainsKey (handle)) {
128
type_map [handle] = type;
163
if (handle != IntPtr.Zero) {
164
if (!type_map.ContainsKey (handle)) {
165
type_map [handle] = type;
133
if (objc_getProtocol (name) != IntPtr.Zero)
134
throw new ArgumentException ("Attempting to register a class named: " + name + " which is a valid protocol");
136
Type parent_type = type.BaseType;
137
string parent_name = null;
138
while (Attribute.IsDefined (parent_type, typeof (ModelAttribute), false))
139
parent_type = parent_type.BaseType;
140
RegisterAttribute parent_attr = (RegisterAttribute) Attribute.GetCustomAttribute (parent_type, typeof (RegisterAttribute), false);
141
parent_name = parent_attr == null ? parent_type.FullName : parent_attr.Name ?? parent_type.FullName;
142
parent = objc_getClass (parent_name);
143
if (parent == IntPtr.Zero && parent_type.Assembly != NSObject.MonoMacAssembly) {
144
// Its possible as we scan that we might be derived from a type that isn't reigstered yet.
145
Class.Register (parent_type, parent_name);
170
if (objc_getProtocol (name) != IntPtr.Zero)
171
throw new ArgumentException ("Attempting to register a class named: " + name + " which is a valid protocol");
176
Type parent_type = type.BaseType;
177
string parent_name = null;
178
while (Attribute.IsDefined (parent_type, typeof (ModelAttribute), false))
179
parent_type = parent_type.BaseType;
180
RegisterAttribute parent_attr = (RegisterAttribute)Attribute.GetCustomAttribute (parent_type, typeof(RegisterAttribute), false);
181
parent_name = parent_attr == null ? parent_type.FullName : parent_attr.Name ?? parent_type.FullName;
146
182
parent = objc_getClass (parent_name);
148
if (parent == IntPtr.Zero) {
149
// This spams mtouch, we need a way to differentiate from mtouch's (ab)use
150
// Console.WriteLine ("CRITICAL WARNING: Falling back to NSObject for type {0} reported as {1}", type, parent_type);
151
parent = objc_getClass ("NSObject");
153
handle = objc_allocateClassPair (parent, name, IntPtr.Zero);
155
foreach (PropertyInfo prop in type.GetProperties (BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) {
156
ConnectAttribute cattr = (ConnectAttribute) Attribute.GetCustomAttribute (prop, typeof (ConnectAttribute));
158
string ivar_name = cattr.Name ?? prop.Name;
159
class_addIvar (handle, ivar_name, (IntPtr) Marshal.SizeOf (typeof (IntPtr)), (ushort) Math.Log (Marshal.SizeOf (typeof (IntPtr)), 2), "@");
162
RegisterProperty (prop, type, handle);
183
if (parent == IntPtr.Zero && parent_type.Assembly != NSObject.MonoMacAssembly) {
184
bool parent_is_wrapper = parent_attr == null ? false : parent_attr.IsWrapper;
185
// Its possible as we scan that we might be derived from a type that isn't reigstered yet.
186
Register (parent_type, parent_name, parent_is_wrapper);
187
parent = objc_getClass (parent_name);
189
if (parent == IntPtr.Zero) {
190
// This spams mtouch, we need a way to differentiate from mtouch's (ab)use
191
// Console.WriteLine ("CRITICAL WARNING: Falling back to NSObject for type {0} reported as {1}", type, parent_type);
192
parent = objc_getClass ("NSObject");
194
handle = objc_allocateClassPair (parent, name, IntPtr.Zero);
196
foreach (PropertyInfo prop in type.GetProperties (BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) {
197
ConnectAttribute cattr = (ConnectAttribute)Attribute.GetCustomAttribute (prop, typeof(ConnectAttribute));
199
string ivar_name = cattr.Name ?? prop.Name;
200
class_addIvar (handle, ivar_name, (IntPtr)Marshal.SizeOf (typeof(IntPtr)), (ushort)Math.Log (Marshal.SizeOf (typeof(IntPtr)), 2), "@");
203
RegisterProperty (prop, type, handle);
165
#if OBJECT_REF_TRACKING
166
class_addMethod (handle, release_builder.Selector, release_builder.Delegate, release_builder.Signature);
167
class_addMethod (handle, retain_builder.Selector, retain_builder.Delegate, retain_builder.Signature);
170
foreach (MethodInfo minfo in type.GetMethods (BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static))
171
RegisterMethod (minfo, type, handle);
173
ConstructorInfo default_ctor = type.GetConstructor (Type.EmptyTypes);
174
if (default_ctor != null) {
175
NativeConstructorBuilder builder = new NativeConstructorBuilder (default_ctor);
177
class_addMethod (handle, builder.Selector, builder.Delegate, builder.Signature);
178
method_wrappers.Add (builder.Delegate);
180
Console.WriteLine ("[CTOR] Registering {0}[0x{1:x}|{2}] on {3} -> ({4})", "init", (int) builder.Selector, builder.Signature, type, default_ctor);
184
foreach (ConstructorInfo cinfo in type.GetConstructors (BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)) {
185
ExportAttribute ea = (ExportAttribute) Attribute.GetCustomAttribute (cinfo, typeof (ExportAttribute));
188
NativeConstructorBuilder builder = new NativeConstructorBuilder (cinfo);
190
class_addMethod (handle, builder.Selector, builder.Delegate, builder.Signature);
191
method_wrappers.Add (builder.Delegate);
193
Console.WriteLine ("[CTOR] Registering {0}[0x{1:x}|{2}] on {3} -> ({4})", ea.Selector, (int) builder.Selector, builder.Signature, type, cinfo);
197
objc_registerClassPair (handle);
199
type_map [handle] = type;
200
custom_types.Add (type);
206
NSObject.OverrideRetainAndRelease (handle);
208
foreach (MethodInfo minfo in type.GetMethods (BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static))
209
RegisterMethod (minfo, type, handle);
211
ConstructorInfo default_ctor = type.GetConstructor (Type.EmptyTypes);
212
if (default_ctor != null) {
213
NativeConstructorBuilder builder = new NativeConstructorBuilder (default_ctor);
215
class_addMethod (handle, builder.Selector, builder.Delegate, builder.Signature);
216
method_wrappers.Add (builder.Delegate);
218
Console.WriteLine ("[CTOR] Registering {0}[0x{1:x}|{2}] on {3} -> ({4})", "init", (int) builder.Selector, builder.Signature, type, default_ctor);
222
foreach (ConstructorInfo cinfo in type.GetConstructors (BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)) {
223
ExportAttribute ea = (ExportAttribute)Attribute.GetCustomAttribute (cinfo, typeof(ExportAttribute));
226
NativeConstructorBuilder builder = new NativeConstructorBuilder (cinfo);
228
class_addMethod (handle, builder.Selector, builder.Delegate, builder.Signature);
229
method_wrappers.Add (builder.Delegate);
231
Console.WriteLine ("[CTOR] Registering {0}[0x{1:x}|{2}] on {3} -> ({4})", ea.Selector, (int) builder.Selector, builder.Signature, type, cinfo);
235
objc_registerClassPair (handle);
237
type_map [handle] = type;
238
custom_types.Add (type, type);
205
244
// FIXME: This doesn't properly handle virtual properties yet
410
473
[DllImport ("/usr/lib/libobjc.dylib")]
411
474
extern static bool class_addIvar (IntPtr cls, string name, IntPtr size, ushort alignment, string types);
412
475
[DllImport ("/usr/lib/libobjc.dylib")]
413
extern static bool class_addMethod (IntPtr cls, IntPtr name, Delegate imp, string types);
476
internal extern static bool class_addMethod (IntPtr cls, IntPtr name, Delegate imp, string types);
414
477
[DllImport ("/usr/lib/libobjc.dylib")]
415
extern static bool class_addMethod (IntPtr cls, IntPtr name, IntPtr imp, string types);
478
internal extern static bool class_addMethod (IntPtr cls, IntPtr name, IntPtr imp, string types);
416
479
[DllImport ("/usr/lib/libobjc.dylib")]
417
480
extern static IntPtr class_getName (IntPtr cls);
418
481
[DllImport ("/usr/lib/libobjc.dylib")]
419
extern static IntPtr class_getSuperclass (IntPtr cls);
482
internal extern static IntPtr class_getSuperclass (IntPtr cls);
483
[DllImport ("/usr/lib/libobjc.dylib")]
484
internal extern static IntPtr class_getMethodImplementation (IntPtr cls, IntPtr sel);
485
[DllImport ("/usr/lib/libobjc.dylib")]
486
internal extern static IntPtr class_getInstanceVariable (IntPtr cls, string name);
488
[MonoNativeFunctionWrapper]
489
delegate IntPtr addPropertyDelegate (IntPtr cls, string name, objc_attribute_prop [] attributes, int count);
490
static addPropertyDelegate addProperty;
491
static bool addPropertyInitialized;
493
static IntPtr class_addProperty (IntPtr cls, string name, objc_attribute_prop [] attributes, int count)
495
if (!addPropertyInitialized) {
496
var handle = Dlfcn.dlopen (Constants.ObjectiveCLibrary, 0);
498
var fptr = Dlfcn.dlsym (handle, "class_addProperty");
499
if (fptr != IntPtr.Zero)
500
addProperty = (addPropertyDelegate) Marshal.GetDelegateForFunctionPointer (fptr, typeof (addPropertyDelegate));
502
Dlfcn.dlclose (handle);
504
addPropertyInitialized = true;
506
if (addProperty == null)
508
return addProperty (cls, name, attributes, count);
511
[StructLayout (LayoutKind.Sequential, CharSet=CharSet.Ansi)]
512
private struct objc_attribute_prop {
513
[MarshalAs (UnmanagedType.LPStr)] internal string name;
514
[MarshalAs (UnmanagedType.LPStr)] internal string value;
421
517
internal struct objc_class {
422
518
internal IntPtr isa;