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