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"); } }
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); }
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); }
/// <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 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); } } }
/// <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); }
/// <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); }
/// <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); }
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 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); } }
/// <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 } }
/// <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); } } }