/// <exclude/> public int requestCheckingOfString_range_types_options_inSpellDocumentWithTag_completionHandler( NSString stringToCheck, NSRange range, ulong checkingTypes, NSDictionary options, int tag, Action<int, NSArray, NSOrthography, int> callback) { RequestCheckingCallback thunk = (IntPtr context, int sequenceNumber, IntPtr resultsPtr, IntPtr orthographyPtr, int wordCount) => { var results = NSObject.Lookup(resultsPtr).To<NSArray>(); var orthography = NSObject.Lookup(orthographyPtr).To<NSOrthography>(); callback(sequenceNumber, results, orthography, wordCount); }; var block = new ExtendedBlock(thunk); int result = Call("requestCheckingOfString:range:types:options:inSpellDocumentWithTag:completionHandler:", stringToCheck, range, checkingTypes, options, tag, block).To<int>(); GC.KeepAlive(block); return result; }
/// <exclude/> public NSObject blockOperationWithBlock(Action callback, out ExtendedBlock block) { Action<IntPtr> thunk = (IntPtr context) => callback(); block = new ExtendedBlock(thunk); NSObject result = Call("blockOperationWithBlock:", block).To<NSObject>(); return result; }
/// <summary>Call this after the native code is done with the block.</summary> /// <remarks>For example, when using a sheet this would be called in the /// completion handler.</remarks> public void Free() { // Users may not bother getting rid of the reference to the cookie, but it's // important that we do get rid of the reference to the delegate so that the // object it is bound to can be GCed. Block = null; lock (ms_lock) { ms_cookies.Remove(this); } }
/// <remarks>Name is used for debugging.</remarks> public BlockCookie(string name, Delegate callback) { Contract.Requires(!string.IsNullOrEmpty(name), "name is null or empty"); Name = name; Block = new ExtendedBlock(callback); lock (ms_lock) { ms_cookies.Add(this); } }
public void Block() { if (ExtendedBlock.HasBlocks()) { NSObject s = new Class("NSString").Call("stringWithUTF8String:", Marshal.StringToHGlobalAuto("hello\nthere")).To<NSObject>(); var lines = new List<string>(); Enumerator e = (IntPtr context, IntPtr line, ref byte stop) => { lines.Add(new NSObject(line).Call("description").ToString()); }; var block = new ExtendedBlock(e); s.Call("enumerateLinesUsingBlock:", block); Assert.AreEqual(2, lines.Count); Assert.AreEqual("hello", lines[0]); Assert.AreEqual("there", lines[1]); } }
/// <exclude/> public NSDirectoryEnumerator enumeratorAtURL_includingPropertiesForKeys_options_errorHandler( NSURL url, NSArray keys, uint mask, Func<NSURL, NSError, bool> callback) { Func<IntPtr, IntPtr, IntPtr, byte> thunk = (IntPtr context, IntPtr urlPtr, IntPtr errorPtr) => { var url2 = NSObject.Lookup(urlPtr).To<NSURL>(); var error = NSObject.Lookup(errorPtr).To<NSError>(); bool stopped = callback(url2, error); return stopped ? (byte) 1 : (byte) 0; }; var block = new ExtendedBlock(thunk); var e = Call("enumeratorAtURL:includingPropertiesForKeys:options:errorHandler:", url, keys, mask, block).To<NSDirectoryEnumerator>(); GC.KeepAlive(block); return e; }
private static void DoFillBuffer(IntPtr buffer, object value, string encoding) { Type type = value != null?value.GetType() : null; switch (encoding) { case "c": if (type == typeof(bool)) { Marshal.WriteByte(buffer, ((bool)value) ? (byte)1 : (byte)0); } else if (type == typeof(sbyte)) { Marshal.WriteByte(buffer, unchecked ((byte)(sbyte)value)); } else { throw new InvalidCallException(string.Format("Expected a Boolean or SByte but got a {0}.", type)); } break; case "C": if (type == typeof(byte)) { Marshal.WriteByte(buffer, (byte)value); } else { throw new InvalidCallException(string.Format("Expected a Byte but got a {0}.", type)); } break; case "s": if (type == typeof(Int16)) { Marshal.WriteInt16(buffer, (Int16)value); } else { throw new InvalidCallException(string.Format("Expected an Int16 but got a {0}.", type)); } break; case "S": if (type == typeof(UInt16)) { Marshal.WriteInt16(buffer, unchecked ((Int16)(UInt16)value)); } else if (type == typeof(Char)) { Marshal.WriteInt16(buffer, unchecked ((Int16)(Char)value)); } else { throw new InvalidCallException(string.Format("Expected a UInt16 or Char but got a {0}.", type)); } break; case "i": case "l": if (type == typeof(Int32)) { Marshal.WriteInt32(buffer, (Int32)value); } else { throw new InvalidCallException(string.Format("Expected an Int32 but got a {0}.", type)); } break; case "I": case "L": if (type == typeof(UInt32)) { Marshal.WriteInt32(buffer, unchecked ((Int32)(UInt32)value)); } else { throw new InvalidCallException(string.Format("Expected a UInt32 but got a {0}.", type)); } break; case "q": if (type == typeof(Int64)) { Marshal.WriteInt64(buffer, (Int64)value); } else { throw new InvalidCallException(string.Format("Expected an Int64 but got a {0}.", type)); } break; case "Q": if (type == typeof(UInt64)) { Marshal.WriteInt64(buffer, unchecked ((Int64)(UInt64)value)); } else { throw new InvalidCallException(string.Format("Expected a UInt64 but got a {0}.", type)); } break; case "f": float f = 0.0f; if (type == typeof(float)) { f = (float)value; } else { throw new InvalidCallException(string.Format("Expected a float but got a {0}.", type)); } Marshal.StructureToPtr(f, buffer, false); break; case "d": double d = 0.0; if (type == typeof(float)) { d = (double)(float)value; } else if (type == typeof(double)) { d = (double)value; } else { throw new InvalidCallException(string.Format("Expected a float or double but got a {0}.", type)); } Marshal.StructureToPtr(d, buffer, false); break; case "@": if (value == null) { Marshal.WriteIntPtr(buffer, IntPtr.Zero); } else { NSObject i = value as NSObject; if (i != null) { Marshal.WriteIntPtr(buffer, (IntPtr)i); } else if (value.GetType() == typeof(IntPtr)) { Marshal.WriteIntPtr(buffer, (IntPtr)value); } else { throw new InvalidCallException(string.Format("Expected an NSObject or IntPtr but got a {0}.", type)); } } break; case "@?": if (value == null) { Marshal.WriteIntPtr(buffer, IntPtr.Zero); } else { if (!ExtendedBlock.HasBlocks()) { throw new InvalidCallException("Objective-C blocks are not supported on this version of the OS."); } ExtendedBlock block = value as ExtendedBlock; if (block != null) { Marshal.WriteIntPtr(buffer, (IntPtr)block.block); } else if (value.GetType() == typeof(IntPtr)) { Marshal.WriteIntPtr(buffer, (IntPtr)value); } else { throw new InvalidCallException(string.Format("Expected an ExtendedBlock or IntPtr but got a {0}.", type)); } } break; case "#": Class k = value as Class; if (k != null) { Marshal.WriteIntPtr(buffer, (IntPtr)k); } else if (value == null) { Marshal.WriteIntPtr(buffer, IntPtr.Zero); } else if (value.GetType() == typeof(IntPtr)) { Marshal.WriteIntPtr(buffer, (IntPtr)value); } else { throw new InvalidCallException(string.Format("Expected a Class but got a {0}.", type)); } break; case ":": Selector sel = value as Selector; if (sel != null) { Marshal.WriteIntPtr(buffer, (IntPtr)sel); } else if (value == null) { Marshal.WriteIntPtr(buffer, IntPtr.Zero); } else if (value.GetType() == typeof(IntPtr)) { Marshal.WriteIntPtr(buffer, (IntPtr)value); } else { throw new InvalidCallException(string.Format("Expected a Selector but got a {0}.", type)); } break; default: if (!DoFillPtrBuffer(encoding, value, buffer) && !DoFillStructBuffer(encoding, value, buffer)) { throw new InvalidCallException("Don't know how to marshal " + encoding + " to a native type."); } break; } }