public string description() { Contract.Requires(!m_deallocated, "ref count is zero"); if (m_instance != IntPtr.Zero) { IntPtr exception = IntPtr.Zero; IntPtr str = DirectCalls.Callp(this, Selector.Description, ref exception); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } IntPtr utf8 = DirectCalls.Callp(str, Selector.UTF8String, ref exception); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } return(Marshal.PtrToStringAuto(utf8)); } else { return("nil"); } }
internal static object Call(IntPtr instance, string name, object[] args) { Contract.Requires(instance != IntPtr.Zero, "instance is zero"); object result; if (name == "alloc" && args.Length == 0) // need this so we can create an auto release pool without leaking NSMethodSignature { IntPtr exception = IntPtr.Zero; IntPtr ip = DirectCalls.Callp(instance, Selector.Alloc, ref exception); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } result = NSObject.Lookup(ip); } else { Selector selector = new Selector(name); MethodSignature sig = new MethodSignature(instance, (IntPtr)selector); Native native = new Native(instance, selector, sig); native.SetArgs(args); result = native.Invoke(); } return(result); }
private SignatureInfo DoEncodingToSig(string encoding) { SignatureInfo info; lock (ms_lock) { if (!ms_encodedTable.TryGetValue(encoding, out info)) { Class klass = new Class("NSMethodSignature"); IntPtr exception = IntPtr.Zero; IntPtr instance = DirectCalls.Callpp(klass, signatureWithObjCTypes, Marshal.StringToHGlobalAnsi(encoding), ref exception); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } if (instance == IntPtr.Zero) { throw new InvalidCallException(string.Format("Couldn't find the method signature for {0}", encoding)); } info = new SignatureInfo(instance); ms_encodedTable.Add(encoding, info); klass.release(); } } return(info); }
// Call imp where args points to buffers containing the arguments and result // is a buffer where the result will be written. public static void Call(IntPtr cif, IntPtr imp, IntPtr result, PtrArray args) { IntPtr exception = IntPtr.Zero; FfiCall(cif, imp, result, args.ToIntPtr(), ref exception); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } }
/// <exclude/> public NSObject init() { IntPtr exception = IntPtr.Zero; IntPtr instance = DirectCalls.Callp(this, Selector.Init, ref exception); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } return(NSObject.Lookup(instance)); }
/// <exclude/> public NSObject retain() { Contract.Requires(!m_deallocated, "ref count is zero"); IntPtr exception = IntPtr.Zero; Unused.Value = DirectCalls.Callp(m_instance, Selector.Retain, ref exception); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } return(this); }
/// <exclude/> public void autorelease() { Contract.Requires(!m_deallocated, "ref count is zero"); if (m_instance != IntPtr.Zero) { IntPtr exception = IntPtr.Zero; Unused.Value = DirectCalls.Callp(this, Selector.Autorelease, ref exception); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } } }
/// <summary>Creates a new uninitialized unmanaged object with a reference count of one.</summary> /// <param name = "name">The class name, e.g. "MyView".</param> /// <remarks>This is commonly used with exported types which can be created via managed code /// (as opposed to via Interface Builder).</remarks> public static IntPtr AllocInstance(string name) { Class klass = new Class(name); IntPtr exception = IntPtr.Zero; IntPtr instance = DirectCalls.Callp(klass, Selector.Alloc, ref exception); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } return(instance); }
// Note that if we don't do all of this caching the memory tests fail. private SignatureInfo DoClassSelectorToSig(IntPtr target, IntPtr selector) { SignatureInfo info = null; IntPtr exception = IntPtr.Zero; IntPtr id = DirectCalls.Callp(target, klass, ref exception); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } lock (ms_lock) { KeyValuePair <IntPtr, IntPtr> key = new KeyValuePair <IntPtr, IntPtr>(id, selector); if (!ms_selectorTable.TryGetValue(key, out info)) { // If target's class is itself then target is a class and we need to use // methodSignatureForSelector to get the class method. Otherwise we'll use // instanceMethodSignatureForSelector to see if the class has an instance // method. If that fails we'll fall back on DoInstanceSelectorToSig to see // if the instance has the method. IntPtr instance; if (id == target) { instance = DirectCalls.Callpp(id, methodSignatureForSelector, selector, ref exception); } else { instance = DirectCalls.Callpp(id, instanceMethodSignatureForSelector, selector, ref exception); } if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } if (instance != IntPtr.Zero) { info = new SignatureInfo(instance); ms_selectorTable.Add(key, info); } } } return(info); }
public int hash() { Contract.Requires(!m_deallocated, "ref count is zero"); int hash = 0; if (m_instance != IntPtr.Zero) { IntPtr exception = IntPtr.Zero; hash = DirectCalls.Calli(this, Selector.Hash, ref exception); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } } return(hash); }
/// <exclude/> public uint retainCount() { Contract.Requires(!m_deallocated, "ref count is zero"); uint count = uint.MaxValue; if (m_instance != IntPtr.Zero) { IntPtr exception = IntPtr.Zero; count = unchecked ((uint)DirectCalls.Calli(m_instance, Selector.RetainCount, ref exception)); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } } return(count); }
/// <exclude/> public void release() { Contract.Requires(!m_deallocated, "ref count is zero"); uint oldCount = retainCount(); IntPtr exception = IntPtr.Zero; Unused.Value = DirectCalls.Callp(m_instance, Selector.Release, ref exception); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } if (oldCount == 1) { m_deallocated = true; // OnDealloc won't be called for registered types so we'll go ahead and set dealloced here } }
private SignatureInfo DoInstanceSelectorToSig(IntPtr target, IntPtr selector) { IntPtr exception = IntPtr.Zero; IntPtr instance = DirectCalls.Callpp(target, methodSignatureForSelector, selector, ref exception); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } if (instance == IntPtr.Zero) { string cn = new NSObject(target).class_().Name; string sn = new Selector(selector).Name; throw new InvalidCallException(string.Format("Couldn't find the method signature for {0} {1}", cn, sn)); } return(new SignatureInfo(instance)); }
public bool isEqual(NSObject rhs) { Contract.Requires(!m_deallocated, "ref count is zero"); bool equal = m_instance == (IntPtr)rhs; if (!equal && m_instance != IntPtr.Zero) { IntPtr exception = IntPtr.Zero; byte result = DirectCalls.CallCp(this, Selector.IsEqual, rhs, ref exception); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } equal = result != 0; } return(equal); }
/// <summary>Allows Call expressions to be chained.</summary> public static object Call(this object instance, Selector selector, params object[] args) { Contract.Requires(selector != null, "selector is null"); Contract.Requires(args != null, "args is null"); object result = new NSObject(IntPtr.Zero); if (instance != null) { IntPtr ptr; if (instance.GetType() == typeof(IntPtr)) { ptr = (IntPtr)instance; } else { ptr = (IntPtr)(NSObject)instance; } if (selector.Name == "init" && args.Length == 0) { IntPtr exception = IntPtr.Zero; IntPtr ip = DirectCalls.Callp(ptr, Selector.Init, ref exception); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } result = NSObject.Lookup(ip); } else { Native invoke = new Native(ptr, selector); invoke.SetArgs(args); result = invoke.Invoke(); } } return(result); }
public SignatureInfo(IntPtr sig) { Contract.Requires(sig != IntPtr.Zero, "sig is nil"); // Get the return encoding. IntPtr exception = IntPtr.Zero; IntPtr buffer = DirectCalls.Callp(sig, methodReturnType, ref exception); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } m_return = Marshal.PtrToStringAnsi(buffer); // Get the number of arguments. int count = DirectCalls.Calli(sig, numberOfArguments, ref exception); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } // Get the encodings for each argument. m_args = new string[count]; for (int i = 0; i < count; ++i) { buffer = DirectCalls.Callpi(sig, getArgumentTypeAtIndex, i, ref exception); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } m_args[i] = Marshal.PtrToStringAnsi(buffer); } }
private static void DoInitClass(string name, string baseName, Type type, string outlets) { Class superClass = new Class(baseName); IntPtr exception = IntPtr.Zero; IntPtr klass = CreateClass(superClass, name, ref exception); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } if (outlets != null) { string[] ivnames = outlets.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); int size = Marshal.SizeOf(typeof(IntPtr)); byte alignment = (byte)Math.Log(size, 2); foreach (string ivname in ivnames) { byte added = class_addIvar(klass, ivname, new IntPtr(size), alignment, "@"); if (added == 0) { throw new ArgumentException(string.Format("Couldn't add outlet {0} to {1}. Is there already an outlet with that name?", ivname, name)); } } } BindingFlags flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static; foreach (MethodInfo info in type.GetMethods(flags)) { if (!info.IsSpecialName && info.DeclaringType.Name != "NSObject") { if (info.Name == "dealloc") { throw new ArgumentException(string.Format("Instead of using {0}::{1}, override OnDealloc.", type, info.Name)); } RegisterAttribute attr = Attribute.GetCustomAttribute(info, typeof(RegisterAttribute), false) as RegisterAttribute; if (attr != null) { DoAddMethod(name, info, attr.Name ?? info.Name, klass, superClass); } else if (char.IsLower(info.Name[0])) { if (info.GetParameters().Length == 0) { DoAddMethod(name, info, info.Name, klass, superClass); } else if (info.GetParameters().Length == 1) { DoAddMethod(name, info, info.Name + ":", klass, superClass); } else if (info.GetParameters().Length >= 2 && info.Name.Contains("_")) { DoAddMethod(name, info, info.Name.Replace('_', ':') + ":", klass, superClass); } else { DoAddMethod(name, info, info.Name, klass, superClass); } } } } MethodInfo info2 = typeof(NSObject).GetMethod("Deallocated", BindingFlags.Instance | BindingFlags.NonPublic); DoAddMethod(name, info2, "dealloc", klass, superClass); RegisterClass(klass, ref exception); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } }
/// <summary>Get or set an ivar.</summary> /// <remarks>Usually these will be Interface Builder outlets.</remarks> public NSObject this[string ivarName] { get { Contract.Requires(!string.IsNullOrEmpty(ivarName), "ivarName is null or empty"); Contract.Requires(!m_deallocated, "ref count is zero"); NSObject result; if (m_instance != IntPtr.Zero) { IntPtr value = IntPtr.Zero; IntPtr ivar = object_getInstanceVariable(m_instance, ivarName, ref value); if (ivar == IntPtr.Zero) { throw new ArgumentException(ivarName + " isn't a valid instance variable"); } result = Lookup(value); } else { result = new NSObject(IntPtr.Zero); } return(result); } set { Contract.Requires(!string.IsNullOrEmpty(ivarName), "ivarName is null or empty"); Contract.Requires(!m_deallocated, "ref count is zero"); if (m_instance != IntPtr.Zero) { // Retain the new value (if any). IntPtr exception = IntPtr.Zero, dummy = IntPtr.Zero; if (!NSObject.IsNullOrNil(value)) { Unused.Value = DirectCalls.Callp(value, Selector.Retain, ref exception); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } } // Release the old value (if any). IntPtr oldValue = IntPtr.Zero; IntPtr ivar = object_getInstanceVariable(m_instance, ivarName, ref oldValue); if (ivar == IntPtr.Zero) { Unused.Value = DirectCalls.Callp(value, Selector.Release, ref dummy); throw new ArgumentException(ivarName + " isn't a valid instance variable"); } if (oldValue != IntPtr.Zero) { Unused.Value = DirectCalls.Callp(oldValue, Selector.Release, ref exception); if (exception != IntPtr.Zero) { Unused.Value = DirectCalls.Callp(value, Selector.Release, ref dummy); CocoaException.Raise(exception); } } // Set the value. ivar = object_setInstanceVariable(m_instance, ivarName, value); } } }
/// <summary>Constructs a managed object which is associated with an unmanaged object.</summary> /// <remarks>In general multiple NSObject instances can be associated with the same unmanaged object. /// The exception is that only one <see cref = "ExportClassAttribute">ExportClassAttribute</see> object can be associated with an /// unmanaged object. If an attempt is made to construct two NSObjects pointing to the same /// exported object an exception will be thrown. (The reason for this is that exported instances may /// have managed state which should be associated with one and only one unmanaged instance).</remarks> public NSObject(IntPtr instance) { m_instance = instance; // note that it's legal to send messages to nil m_class = IntPtr.Zero; if (m_instance != IntPtr.Zero) { // It's a little inefficient to always grab this information, but it makes // dumping objects much easier because we can safely do it even when ref // counts are zero. IntPtr exception = IntPtr.Zero; m_class = DirectCalls.Callp(m_instance, Selector.Class, ref exception); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } m_baseClass = DirectCalls.Callp(m_class, Selector.SuperClass, ref exception); if (exception != IntPtr.Zero) { CocoaException.Raise(exception); } #if DEBUG if (SaveStackTraces) { var stack = new System.Diagnostics.StackTrace(1); StackTrace = new string[stack.FrameCount]; for (int i = 0; i < stack.FrameCount; ++i) // TODO: provide a MaxStackDepth method? { StackFrame frame = stack.GetFrame(i); if (!string.IsNullOrEmpty(frame.GetFileName())) { StackTrace[i] = string.Format("{0}|{1} {2}:{3}", frame.GetMethod().DeclaringType, frame.GetMethod(), frame.GetFileName(), frame.GetFileLineNumber()); } else { StackTrace[i] = string.Format("{0}|{1}", frame.GetMethod().DeclaringType, frame.GetMethod()); } } } #endif lock (ms_instancesLock) { bool exported; Type type = GetType(); if (!ms_exports.TryGetValue(type, out exported)) // GetCustomAttribute turns out to be very slow { ExportClassAttribute attr = Attribute.GetCustomAttribute(type, typeof(ExportClassAttribute)) as ExportClassAttribute; exported = attr != null; ms_exports.Add(type, exported); } if (exported) { if (ms_instances.ContainsKey(instance)) { throw new InvalidOperationException(type + " is being constructed twice with the same id, try using the Lookup method."); } ms_instances.Add(instance, this); } } #if DEBUG ms_refs.Add(this); #endif } }