Exemplo n.º 1
0
        // 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);
        }
Exemplo n.º 2
0
        // Use ffi_type*'s to create an ffi_cif*. Note that libffi will save the atypes
        // pointer so we can't free it (and we can't use an IntPtr[] without explicity
        // saving the array).
        public static IntPtr AllocCif(IntPtr rtype, PtrArray atypes)
        {
            if (atypes[atypes.Length - 1] != IntPtr.Zero)
                throw new ArgumentException("atypes should be null terminated");

            IntPtr cif = AllocCif(atypes.Length - 1, rtype, atypes.ToIntPtr());

            if (cif.ToInt32() == 1)
                throw new ArgumentException("FFI_BAD_TYPEDEF");
            else if (cif.ToInt32() == 2)
                throw new ArgumentException("FFI_BAD_ABI");

            return cif;
        }
Exemplo n.º 3
0
        private void DoGetPropsString(StringBuilder builder)
        {
            Class klass = class_();
            while (klass != null && (IntPtr) klass != IntPtr.Zero)
            {
                int count = 0;
                IntPtr buffer = class_copyPropertyList((IntPtr) klass, ref count);

                if (count > 0)
                {
                    PtrArray ivars = new PtrArray(buffer, count);

                    for (int i = 0; i < count; ++i)
                    {
                        IntPtr name = property_getName(ivars[i]);	// property_getAttributes?
                        string s = Marshal.PtrToStringAnsi(name);
                        builder.AppendLine(s);
                    }
                }

                Marshal.FreeHGlobal(buffer);

                klass = klass.BaseClass;
            }
        }
Exemplo n.º 4
0
        private void DoGetIvarString(StringBuilder builder, bool includePrivate)
        {
            Class klass = class_();
            while (klass != null && (IntPtr) klass != IntPtr.Zero)
            {
                int count = 0;
                IntPtr buffer = class_copyIvarList((IntPtr) klass, ref count);

                if (count > 0)
                {
                    PtrArray ivars = new PtrArray(buffer, count);

                    for (int i = 0; i < count; ++i)
                    {
                        IntPtr name = ivar_getName(ivars[i]);
                        string s = Marshal.PtrToStringAnsi(name);
                        if (includePrivate || (s.Length > 0 && s[0] != '_'))
                            builder.AppendLine(s);
                    }
                }

                Marshal.FreeHGlobal(buffer);

                klass = klass.BaseClass;
            }
        }
Exemplo n.º 5
0
        private void DoAddMethods(Class klass, List<List<string>> table, bool includePrivate)
        {
            int count = 0;
            IntPtr buffer = class_copyMethodList((IntPtr) klass, ref count);

            if (count > 0)
            {
                PtrArray methods = new PtrArray(buffer, count);

                for (int i = 0; i < count; ++i)
                {
                    Selector sel = new Selector(method_getName(methods[i]));
                    if (includePrivate || (sel.Name.Length > 0 && sel.Name[0] != '_'))
                    {
                        List<string> row = new List<string>();
                        row.Add(sel.Name);

                        IntPtr imp = method_getImplementation(methods[i]);
                        row.Add(imp.ToInt32().ToString("X"));

                        table.Add(row);
                    }
                }
            }

            Marshal.FreeHGlobal(buffer);
        }
Exemplo n.º 6
0
        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;
        }
Exemplo n.º 7
0
            public StackFrame(MethodSignature sig)
            {
                m_returnEncoding = sig.GetReturnEncoding();

                IntPtr resultType = Ffi.GetFfiType(m_returnEncoding);
                m_resultBuffer = Ffi.CreateBuffer(m_returnEncoding);

                int numArgs = sig.GetNumArgs();
                m_argBuffers = new PtrArray(numArgs);
                m_argTypes = new PtrArray(numArgs + 1);

                for (int i = 0; i < numArgs; ++i)
                {
                    string encoding = sig.GetArgEncoding(i);
                    m_argBuffers[i] = Ffi.CreateBuffer(encoding);
                    m_argTypes[i] = Ffi.GetFfiType(encoding);
                }

                m_argTypes[numArgs] = IntPtr.Zero;

                m_cif = Ffi.AllocCif(resultType, m_argTypes);
            }
Exemplo n.º 8
0
        private static IntPtr DoAllocStructFfiType(string sname, string pencoding)
        {
            List<IntPtr> fieldTypes = new List<IntPtr>();

            int index = 0;
            while (index < pencoding.Length)
            {
                if (pencoding[index] == '{')
                {
                    int i = pencoding.IndexOf('=', index);
                    int j = pencoding.IndexOf('}', index);
                    string sname2 = pencoding.Substring(index + 1, i - index - 1);
                    string pencoding2 = pencoding.Substring(i + 1, j - i - 1);
                    fieldTypes.Add(DoAllocStructFfiType(sname2, pencoding2));

                    index = j + 1;
                }
                else
                {
                    char code = DoGetCode(pencoding[index++].ToString());
                    if (code == '\x0')
                        throw new InvalidCallException("Can only marshal structs whose fields are primitive types or structs with primitive types and " + sname + " isn't.");

                    fieldTypes.Add(GetFfiType(code));
                }
            }

            fieldTypes.Add(IntPtr.Zero);

            // Note that we don't free these, but that should be OK since
            // there should only be a limited number of structs we marshal
            // and it doesn't hurt to cache the ffi_type* anyway.
            PtrArray ft = new PtrArray(fieldTypes.Count);
            for (int i = 0; i < ft.Length; ++i)
                ft[i] = fieldTypes[i];

            IntPtr result = AllocStructFfiType( ft.ToIntPtr());

            return result;
        }