コード例 #1
0
ファイル: Native.cs プロジェクト: divyang4481/mobjc
        internal Native(IntPtr target, Selector selector, IntPtr imp, MethodSignature sig)
        {
            Contract.Requires(selector != null, "selector is null");
            Contract.Requires(target == IntPtr.Zero || imp != IntPtr.Zero, "imp is null");

            m_target = target;

            if (m_target != IntPtr.Zero)
            {
                if (ms_stackFrames == null)
                {
                    ms_stackFrames = new Dictionary <MethodSignature, StackFrame>();                    // note that we have to do this here so each thread gets its own dictionary
                }
                m_selector = selector;
                m_imp      = imp;
                m_sig      = sig ?? new MethodSignature(target, (IntPtr)selector);

                if (!ms_stackFrames.TryGetValue(m_sig, out m_stackFrame))
                {
                    m_stackFrame = new StackFrame(m_sig);
                    ms_stackFrames.Add(m_sig, m_stackFrame);
                }

                Ffi.FillBuffer(m_stackFrame.ArgBuffers[0], target, "@");
                Ffi.FillBuffer(m_stackFrame.ArgBuffers[1], m_selector, ":");
            }
        }
コード例 #2
0
ファイル: Native.cs プロジェクト: divyang4481/mobjc
        /// <summary>Note that this may be be called once and <c>Invoke</c> many times.</summary>
        public void SetArgs(params object[] args)
        {
            Contract.Requires(args != null, "args is null");

            if (m_target != IntPtr.Zero)
            {
                if (m_sig.GetNumArgs() != 2 + args.Length)
                {
                    throw new InvalidCallException(string.Format("{0} takes {1} arguments but was called with {2} arguments", m_selector, m_sig.GetNumArgs() - 2, args.Length));
                }

                for (int i = 0; i < args.Length; ++i)
                {
                    string encoding = m_sig.GetArgEncoding(i + 2);
                    Ffi.FillBuffer(m_stackFrame.ArgBuffers[i + 2], args[i], encoding);
                }
            }
        }
コード例 #3
0
ファイル: Managed.cs プロジェクト: divyang4481/mobjc
        internal IntPtr Call(IntPtr dummy, IntPtr resultBuffer, IntPtr argBuffers)
        {
            Unused.Value = dummy;

            IntPtr exception = IntPtr.Zero;

            try
            {
                // Get the this pointer for the method we're calling.
                PtrArray argArray = new PtrArray(argBuffers, m_signature.GetNumArgs() + 2);
                NSObject instance = (NSObject)Ffi.DrainBuffer(argArray[0], "@");

                // Get the selector for the method that was called.
                // Get the method arguments.
                string   encoding;
                object[] args = new object[m_signature.GetNumArgs() - 2];
                for (int i = 0; i < args.Length; ++i)
                {
                    encoding = m_signature.GetArgEncoding(i + 2);
                    if (encoding == "@")
                    {
                        args[i] = (NSObject)Ffi.DrainBuffer(argArray[i + 2], encoding);
                    }
                    else
                    {
                        args[i] = Ffi.DrainBuffer(argArray[i + 2], encoding);
                    }

                    // Native code doesn't distinguish between unsigned short and unichar
                    // so we need to fix things up here.
                    Type ptype = m_info.GetParameters()[i].ParameterType;
                    if (ptype == typeof(char))
                    {
                        args[i] = (char)(UInt16)args[i];
                    }
                    else if (ptype != typeof(NSObject) && typeof(NSObject).IsAssignableFrom(ptype))
                    {
                        IntPtr ip = (IntPtr)(NSObject)args[i];

                        args[i] = NSObject.Lookup(ip);
                        if (args[i] == null && ip != IntPtr.Zero)
                        {
                            throw new InvalidCallException(string.Format("Couldn't create a {0} when calling {1}. Is {0} registered or exported?", ptype, m_info.Name));
                        }
                    }

                    // Provide a better error message than the uber lame: "parameters".
                    if (args[i] != null && !ptype.IsAssignableFrom(args[i].GetType()))
                    {
                        throw new InvalidCallException(string.Format("Expected a {0} when calling {1} but have a {2}.", ptype, m_info.Name, args[i].GetType()));
                    }
                }

                // Call the method,
                object value = m_info.Invoke(instance, args);

                // and marshal the result.
                encoding = m_signature.GetReturnEncoding();
                if (encoding == "c" || encoding == "C" || encoding == "s" || encoding == "S")                   // per 'man ffi_call' small results must be stuffed into "storage that is sizeof(long) or larger"
                {
                    int r = Convert.ToInt32(value);
                    Ffi.FillBuffer(resultBuffer, r, "l");
                }
                else if (encoding != "v" && encoding != "Vv")
                {
                    Ffi.FillBuffer(resultBuffer, value, encoding);
                }
            }
            catch (TargetInvocationException ie)
            {
                if (LogException != null)
                {
                    LogException(ie);
                }
                else
                {
                    DoLogException(ie);
                }
                exception = DoCreateNativeException(ie.InnerException);
            }
            catch (Exception e)
            {
                if (LogException != null)
                {
                    LogException(e);
                }
                else
                {
                    DoLogException(e);
                }
                exception = DoCreateNativeException(e);
            }

            return(exception);
        }