binding objective-c libraries, miguel de icaza

48
MonoTouch/iOS Native Interop Xamarin Inc

Upload: xamarin

Post on 10-May-2015

1.944 views

Category:

Technology


3 download

TRANSCRIPT

Page 1: Binding Objective-C Libraries, Miguel de Icaza

MonoTouch/iOS Native Interop

Xamarin Inc

Page 2: Binding Objective-C Libraries, Miguel de Icaza

Agenda• When to Bind• How to bind • Improving the binding

Page 3: Binding Objective-C Libraries, Miguel de Icaza

INTRODUCTION TO BINDINGS

Page 4: Binding Objective-C Libraries, Miguel de Icaza

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

Page 5: Binding Objective-C Libraries, Miguel de Icaza

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

Page 6: Binding Objective-C Libraries, Miguel de Icaza

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

Page 7: Binding Objective-C Libraries, Miguel de Icaza

Configuring Objective Sharpie

Page 8: Binding Objective-C Libraries, Miguel de Icaza

Header Files + Namespace

Page 9: Binding Objective-C Libraries, Miguel de Icaza

Generating the IDL

Page 10: Binding Objective-C Libraries, Miguel de Icaza

MonoTouch Binding Project

Page 11: Binding Objective-C Libraries, Miguel de Icaza

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

Page 12: Binding Objective-C Libraries, Miguel de Icaza

Example: C# Interface DefinitionObjective-C@interface MagicBeans : NSObject {

// …}-(id) initWithString:(NSString*)msg;+(NSArray*) getAllBeans();-(void) grow;-(void) harvest:(NSDate *) time;@end

Page 13: Binding Objective-C Libraries, Miguel de Icaza

Example: C# Interface DefinitionObjective-C@interface MagicBeans : NSObject {

// …}-(id) initWithString:(NSString*)msg;+(NSArray*) getAllBeans();-(void) grow;-(void) harvest: (NSDate *) time;@end

C# 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);

}

Page 14: Binding Objective-C Libraries, Miguel de Icaza

Binding “MagicBeans” libraryMagicBeans.dll

Enumerations, Structures

C# Interface Definition

Curated Extensions

libMagicBeans.a

C# Source Native Binary .NET Binary

Single deployment unit

Contains:• C# binding• Native Library• Assets (artwork,

audio)

Page 15: Binding Objective-C Libraries, Miguel de Icaza

OBJECTIVE SHARPIE

Page 16: Binding Objective-C Libraries, Miguel de Icaza

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– http://bit.ly/objective-sharpie

Page 17: Binding Objective-C Libraries, Miguel de Icaza

BASICS OF BINDINGS

Page 18: Binding Objective-C Libraries, Miguel de Icaza

Basics of Bindings• Binding Classes• Binding Protocols• Methods, Properties

– Type mappings– Arrays– Strings

• Delegate classes (and Events)• Exposing Weak and Strong Types• Binding Blocks

Page 19: Binding Objective-C Libraries, Miguel de Icaza

Class Declarations Objective-C C# Mapping Result

Class Declaration

@interface Foo : Bar [BaseType (typeof (Bar))]interfaceFoo

C# class

Class adopting protocol

@interface Foo : Bar <Pro>

[BaseType (typeof (Bar))]interfaceFoo : Pro

C# class, inlined protocol methods

Protocol @protocol Foo <Bar> [BaseType (typeof (Bar))][Model]interface Foo

C# class with methods to override

Category @interface Foo(Cute)

[BaseType (typeof (Foo))]interface Cute

C# extensions method class

Page 20: Binding Objective-C Libraries, Miguel de Icaza

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 ();

Page 21: Binding Objective-C Libraries, Miguel de Icaza

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)

Page 22: Binding Objective-C Libraries, Miguel de Icaza

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

Page 23: Binding Objective-C Libraries, Miguel de Icaza

Binding Correctness• [Export] definitions might have errors– Transcription errors– Accidental setters, or wrong getters

• Create a unit test– Subclass ApiCtorInitTest

Page 24: Binding Objective-C Libraries, Miguel de Icaza

Testing your APIs[TestFixture]public class BindingCtorTest : ApiCtorInitTest { protected override Assembly Assembly { get { return typeof (CCAccelAmplitude).Assembly; } } }}

Page 25: Binding Objective-C Libraries, Miguel de Icaza

Core Type MappingsObjective-C C#

BOOL, GLBoolean bool

NSString * C# string or NSString

char * [PlainString] string

NSInteger, NSUInteger int, uint

CGRect, CGPoint, CGSize RectangleF, PointF, SizeF

id NSObject

SEL ObjCRuntime.Selector

dispatch_queue_t CoreFoundation.DispatchQueue

CGFloat, GLFloat float

Page 26: Binding Objective-C Libraries, Miguel de Icaza

Arrays• NSArray represents arrays– Untyped, no code completion

• When binding, use strong types instead– “NSArray” becomes “UIView []”– Requires a trip to the documentation

Page 27: Binding Objective-C Libraries, Miguel de Icaza

LINKING LIBRARIES

Page 28: Binding Objective-C Libraries, Miguel de Icaza

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

Page 29: Binding Objective-C Libraries, Miguel de Icaza

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

Page 30: Binding Objective-C Libraries, Miguel de Icaza

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

Page 31: Binding Objective-C Libraries, Miguel de Icaza

SmartLink effect on Samples

ATMHud

BeebleS

DK

Couchbase

Datatra

ns

DropBoxS

ync -

DropBoxS

yncSa

mpleiOS

DropBoxS

ync -

DropBoxS

yncSa

mpleMTD

Flurry

Analytics

GCDiscree

tNotificati

on

GoogleAnaly

tics

GoogleMap

s

MBProgre

ssHud

MGSplitV

iewContro

ller

RedLas

er

SDSe

gmen

tedContro

l

TestF

light

TimesS

quare

WEP

opover

ZipArch

ive -

2,000

4,000

6,000

All codeSmart Linking

Page 32: Binding Objective-C Libraries, Miguel de Icaza

Size Savings

ATMHud

BeebleS

DK

Couchbase

Datatra

ns

DropBoxS

ync -

DropBoxS

yncSa

mpleiOS

DropBoxS

ync -

DropBoxS

yncSa

mpleMTD

Flurry

Analytics

GCDiscree

tNotificati

on

GoogleAnaly

tics

GoogleMap

s

MBProgre

ssHud

MGSplitV

iewContro

ller

RedLas

er

SDSe

gmen

tedContro

l

TestF

light

TimesS

quare

WEP

opover

ZipArch

ive0

100,000200,000300,000400,000500,000

Savings

Page 33: Binding Objective-C Libraries, Miguel de Icaza

ADVANCED BINDING FEATURES

Page 34: Binding Objective-C Libraries, Miguel de Icaza

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 and

System.Drawing.SizeF

Page 35: Binding Objective-C Libraries, Miguel de Icaza

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

Page 36: Binding Objective-C Libraries, Miguel de Icaza

Observing APIUsage:

var obs = NSFileHandle.Notifications.ObserveReadCompletion ((sender, args) => { Console.WriteLine (args.AvailableData); Console.WriteLine (args.UnixError);});

Stop notifications:obs.Dispose ();

Page 37: Binding Objective-C Libraries, Miguel de Icaza

Binding Notification – Two StepsDefine Notification Payload• Optional• Interface without [Export]• Use EventArgs in type name

public interface NSFileHandleReadEventArgs { [Export ("NSFileHandleNotificationDataItem")] NSData AvailableData { get; }

[Export ("NSFileHandleError”)] int UnixErrorCode { get; }}

Annotate Fields• Annotate fields with

[Notification] attribute• Use type if you have a

payload

[Field ("NSFileHandleReadCompletionNotification")][Notification (typeof (NSFileHandleReadEventArgs))]NSString ReadCompletionNotification { get; }

Page 38: Binding Objective-C Libraries, Miguel de Icaza

Generated Notificationspublic class NSFileHandle { public class Notifications {

// Return value is a token to stop receiving notifications public static NSObject ObserveReadCompletion (EventHandler<MonoTouch.Foundation.NSFileHandleReadEventArgs> handler) }}

Usage:

NSFileHandle.Notifications.ObserveReadCompletion ((sender, args) => { Console.WriteLine (args.AvailableData); Console.WriteLine (args.UnixError);});

Page 39: Binding Objective-C Libraries, Miguel de Icaza

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.

Page 40: Binding Objective-C Libraries, Miguel de Icaza

CURATED EXTENSIONS

Page 41: Binding Objective-C Libraries, Miguel de Icaza

• Add () methods, for initializing collections• Exposing high-level APIs• Strong typed APIs for Dictionaries• Implement ToString ()• Iterators and IEnumerable

Page 42: Binding Objective-C Libraries, Miguel de Icaza

Curated ExtensionsUsage• Improve the C# experience

• Expose some common methods (enumerators, LINQ, strong types)

• Re-surface internal methods

Examplepartial class MagicBeans {

// Enable code like this: // // foreach (var j in myBean){ // } //

public IEnumerator<Bean> GetEnumerator() { foreach (var bean in GetAllBeans())

yield return bean; }}

Page 43: Binding Objective-C Libraries, Miguel de Icaza

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

Page 44: Binding Objective-C Libraries, Miguel de Icaza

Strong typed wrappers• Discovery of properties with IDE’s Code

Completion.• 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

Page 45: Binding Objective-C Libraries, Miguel de Icaza

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)

Page 46: Binding Objective-C Libraries, Miguel de Icaza

Using DictionaryContainer• DictionaryContainer provides bridge– Subclass DictionaryContainer– Provide a constructor that takes NSDictionary– Provide constructor with fresh

NSMutableDictionary• Use GetXxxValue and SetXxxValue

Page 47: Binding Objective-C Libraries, Miguel de Icaza

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

Page 48: Binding Objective-C Libraries, Miguel de Icaza

Expose Iterators• Useful for LINQ• Lets your objects be consumed by LINQ• Implement GetEnumerator• Use yield to invoke underlying APIs