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