Your SlideShare is downloading. ×
Binding Objective-C Libraries, Miguel de Icaza
Upcoming SlideShare
Loading in...5

Thanks for flagging this SlideShare!

Oops! An error has occurred.


Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Binding Objective-C Libraries, Miguel de Icaza


Published on

Published in: Technology, Education

  • Be the first to comment

No Downloads
Total Views
On Slideshare
From Embeds
Number of Embeds
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

No notes for slide


  • 1. MonoTouch/iOS Native InteropXamarin Inc
  • 2. Agenda• When to Bind• How to bind• Improving the binding
  • 4. Xamarin.iOS Native Interop• Consume Objective-C or C code– Integrated existing code– Move performance sensitive code to C/assembly– Adopt third party libraries– Adopt third party controls/frameworks• At the core of Xamarin.iOS itself
  • 5. Integration with Native Libraries• iOS Native Libraries– Core libraries written in C– High-level libraries written in Objective-C• Consuming C Libraries:– Uses standard .NET Platform/Invoke support• Consuming Objective-C Libraries:– Binding Projects– “Projects” Objective-C to C#– Provides full integration with native object hierarchy
  • 6. Mono/Objective-C Bindings• Used by MonoTouch itself– Every Objective-C API is surfaced this way.• Tool produces C# libraries that:– Map 1:1 to underlying Objective-C libraries– Allow instantiating Objective-C classes– Allow subclassing/overwriting of behavior– Can extend Objective-C with C# idioms
  • 7. Configuring Objective Sharpie
  • 8. Header Files + Namespace
  • 9. Generating the IDL
  • 10. MonoTouch Binding Project
  • 11. Creating a Binding• Enumerations and Structures– Contain core definitions used by the interface• C# Interface Definition– Defines how to project Objective-C to C#– Name mapping, Overloads• Curated Extensions:– Contains helper features to simplify development– Add strongly-typed features
  • 12. Example: C# Interface DefinitionObjective-C@interface MagicBeans : NSObject {// …}-(id) initWithString:(NSString*)msg;+(NSArray*) getAllBeans();-(void) grow;-(void) harvest:(NSDate *) time;@end
  • 13. Example: C# Interface DefinitionObjective-C@interface MagicBeans : NSObject {// …}-(id) initWithString:(NSString*)msg;+(NSArray*) getAllBeans();-(void) grow;-(void) harvest: (NSDate *) time;@endC# Interface Definition[BaseType (typeof (NSObject))]Interface MagicBean {[Export (“initWithString:”)]IntPtr Constructor (string msg);[Static, Export (“getAllBeans”)]MagicBeans [] GetAllBeans ();[Export (“grow”)]void Grow ();[Export (“harvest:”)]void Harvest (NSDate time);}
  • 14. Binding “MagicBeans” libraryMagicBeans.dllEnumerations,StructuresC# InterfaceDefinitionCuratedExtensionslibMagicBeans.aC# Source Native Binary .NET BinarySingle deployment unitContains:• C# binding• Native Library• Assets (artwork,audio)
  • 16. Compiler Driven Bindings• ObjectiveSharpie Tool– Uses LLVM’s Objective-C compiler to parse API– Applies standard Binding rules– Generates Baseline C# IDL for you– Then you modify• Available Today–
  • 18. Basics of Bindings• Binding Classes• Binding Protocols• Methods, Properties– Type mappings– Arrays– Strings• Delegate classes (and Events)• Exposing Weak and Strong Types• Binding Blocks
  • 19. Class DeclarationsObjective-C C# Mapping ResultClassDeclaration@interface Foo : Bar [BaseType (typeof (Bar))]interfaceFooC# classClassadoptingprotocol@interface Foo : Bar<Pro>[BaseType (typeof (Bar))]interfaceFoo : ProC# class, inlinedprotocol methodsProtocol @protocol Foo <Bar> [BaseType (typeof (Bar))][Model]interface FooC# class with methodsto overrideCategory @interfaceFoo(Cute)[BaseType (typeof (Foo))]interface CuteC# extensions methodclass
  • 20. Objective-C Method Selectors-(float) getNumber;• Meaning:– “-” means it is an instance method– Float return type– Selector name is “getNumber”• C# IDL:*Export (“getNumber”)+float GetNumber ();
  • 21. Objective-C Method Selectors+(float) add:(int) first and:(int) second;• Meaning:– “+” means it is a static method– Float return type– Takes two int arguments– Selector name is “add:and:”• C# IDL:*Export (“add:and:”)+float Add (int first, int second)
  • 22. Objective-C Property Selectors@property (readwrite) int foo;• Meaning:– Property is read/write– int return type– Selector pair is: “foo” (get) and “setFoo:” (set)• C# IDL:*Export (“foo”)+int Foo { get; set; }
  • 23. Binding Correctness• [Export] definitions might have errors– Transcription errors– Accidental setters, or wrong getters• Create a unit test– Subclass ApiCtorInitTest
  • 24. Testing your APIs[TestFixture]public class BindingCtorTest : ApiCtorInitTest {protected override Assembly Assembly {get {return typeof (CCAccelAmplitude).Assembly; }}}}
  • 25. Core Type MappingsObjective-C C#BOOL, GLBoolean boolNSString * C# string or NSStringchar * [PlainString] stringNSInteger, NSUInteger int, uintCGRect, CGPoint, CGSize RectangleF, PointF, SizeFid NSObjectSEL ObjCRuntime.Selectordispatch_queue_t CoreFoundation.DispatchQueueCGFloat, GLFloat float
  • 26. Arrays• NSArray represents arrays– Untyped, no code completion• When binding, use strong types instead– “NSArray” becomes “UIView *+”– Requires a trip to the documentation
  • 28. Linking Libraries• Use assembly-level attribute LinkWith– [assembly:LinkWith (…)• Specify static and dynamic dependencies– Frameworks (for required dependencies)– WeakFrameworks (for optional dependencies)– Pass system linker flags• Libraries referenced are bundled into DLL– Simplifies distribution (single DLL contains all resources)– Unpacked before the final build
  • 29. Native Libraries• FAT libraries– One libFoo.a may contain x86, arm, thumb code– Not all libraries build have all targets– Make sure you build all the supported targets– See monotouch-bindings’ Makefile for samples• IDE automatically examines fat libraries– And produces the proper LinkWith attribute
  • 30. New: SmartLink• By default, all native code is linked-in• SmartLink merges Mono and System linker– Only code that is directly referenced is included– Caveat: dynamic Objective-C code can fail– Big savings
  • 31. SmartLink effect on Samples-2,0004,0006,000All codeSmart Linking
  • 32. Size Savings0100,000200,000300,000400,000500,000Savings
  • 34. Binding Public Variables• Mapped to properties in C#• Use the Field attribute.• Provide get or get/set[Field (“FooServiceKey”, “__Internal”)]NSString ServiceKey { get; set; }• Use “__Internal” for binding libraries• Supports NSArray, NSString, int, long, float, double, IntPtr andSystem.Drawing.SizeF
  • 35. Notifications• Basic API:– NSNotificationCenter takes a string + method– Invokes method when notification is posted– Contains an NSDictionary with notification data• We want a strongly typed API:– Simplify discovery of available notifications– Simplify discovery of parameters , consumption
  • 36. Observing APIUsage:var obs = NSFileHandle.Notifications.ObserveReadCompletion ((sender, args) => {Console.WriteLine (args.AvailableData);Console.WriteLine (args.UnixError);});Stop notifications:obs.Dispose ();
  • 37. Binding Notification – Two StepsDefine Notification Payload• Optional• Interface without [Export]• Use EventArgs in type namepublic interface NSFileHandleReadEventArgs {[Export ("NSFileHandleNotificationDataItem")]NSData AvailableData { get; }[Export ("NSFileHandleError”)]int UnixErrorCode { get; }}Annotate Fields• Annotate fields with[Notification] attribute• Use type if you have apayload[Field ("NSFileHandleReadCompletionNotification")][Notification (typeof (NSFileHandleReadEventArgs))]NSString ReadCompletionNotification { get; }
  • 38. Generated Notificationspublic class NSFileHandle {public class Notifications {// Return value is a token to stop receiving notificationspublic staticNSObject ObserveReadCompletion(EventHandler<MonoTouch.Foundation.NSFileHandleReadEventArgs> handler)}}Usage:NSFileHandle.Notifications.ObserveReadCompletion ((sender, args) => {Console.WriteLine (args.AvailableData);Console.WriteLine (args.UnixError);});
  • 39. Async• Easy Async, turn any method of the form:void Foo (arg1, arg2,.., argN, callback cb)• Just add [Async] to the contract and it does:void Foo (arg1, arg2, .., argN, callback cb)Task FooAsync (arg1, arg2, .., argN)• Callback must be a delegate type.
  • 41. • Add () methods, for initializing collections• Exposing high-level APIs• Strong typed APIs for Dictionaries• Implement ToString ()• Iterators and IEnumerable
  • 42. Curated ExtensionsUsage• Improve the C# experience• Expose some commonmethods(enumerators, LINQ, strongtypes)• Re-surface internal methodsExamplepartial class MagicBeans {// Enable code like this://// foreach (var j in myBean){// }//public IEnumerator<Bean> GetEnumerator(){foreach (var bean in GetAllBeans())yield return bean;}}
  • 43. NSDictionary As Options• Many APIs in iOS take NSDictionary “options”– Annoying to find acceptable keys and values– Requires a trip to the documentation– Often docs are bad, see StackOverflow or Google– Invalid values are ignored or– Generate an error with no useful information
  • 44. Strong typed wrappers• Discovery of properties with IDE’s CodeCompletion.• Let the IDE guide you• Only valid key/values allowed• Skip a trip to the documentation• Avoid ping-pong in docs• Avoid error guesswork for your users
  • 45. NSDictionary vs Strong TypesWith NSDictionaryvar options = new NSDictionary (AVAudioSettings.AVLinearPCMIsFloatKey,new NSNumber (1),AVAudioSettings.AVEncoderBitRateKey,new NSNumber (44000));new AVAssetReaderAudioMixOutput(tr, options);With Strong Typesvar options = new AudioSettings () {AVLinearPCMFloat = true,EncoderBitRate = 44000};new AVAssetReaderAudioMixOutput (tr, options)
  • 46. Using DictionaryContainer• DictionaryContainer provides bridge– Subclass DictionaryContainer– Provide a constructor that takes NSDictionary– Provide constructor with freshNSMutableDictionary• Use GetXxxValue and SetXxxValue
  • 47. DictionaryContainer Samplepublic class AudioSettings : DictionaryContainer{public AudioSettings () : base (new NSMutableDictionary ()) {}public AudioSettings (NSDictionary dictionary) : base (dictionary) {}public AudioFormatType? Format {set {SetNumberValue (AVAudioSettings.AVFormatIDKey, (int?) value);}get {return (AudioFormatType?)GetInt32Value (AVAudioSettings.AVFormatIDKey);}}
  • 48. Expose Iterators• Useful for LINQ• Lets your objects be consumed by LINQ• Implement GetEnumerator• Use yield to invoke underlying APIs