Exemple #1
0
        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");
            }
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        /// <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));
        }
Exemple #5
0
        /// <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);
                }
            }
        }
Exemple #6
0
        /// <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);
        }
Exemple #7
0
        /// <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);
        }
Exemple #8
0
        // 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);
        }
Exemple #9
0
        /// <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);
        }
Exemple #10
0
        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);
        }
Exemple #11
0
        /// <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
            }
        }
Exemple #12
0
        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));
        }
Exemple #13
0
        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);
        }
Exemple #14
0
        /// <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);
        }
Exemple #15
0
        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);
            }
        }
Exemple #16
0
        /// <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
            }
        }
Exemple #17
0
        /// <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);
                }
            }
        }