Today we released MonoMac, a new foundation for building Cocoa
applications on OSX using Mono.

MonoMac is the result of years of experimentation in
blending .NET with Objective-C and is inspired by the same
design principles that we used for MonoTouch.

It is also the result of weekend hacking as our day to day
work revolves around Mono's efforts on Linux servers, Linux
desktops, Visual Studio integration and our mobile
efforts. Luckily, it shares some components with MonoTouch.

Background

Many years ago Geoff Norton produced CocoaSharp, the first
set of .NET bindings to the Cocoa API. CocoaSharp was a fine
first binding at the time and it was a good place to start
learning about the challenges of binding Objective-C APIs to
be consumed by .NET clients.

Over the years three other frameworks were created to
integrate the Objective-C world and the Objective-C APIs with
C# and other .NET languages. Each one of these new frameworks
had its pros and cons, and a year ago
we made
a call for all three competing frameworks to be merged,
but sadly nothing came out of it.

When we created MonoTouch, we wanted a binding for the
Cocoa APIs that would fit the patterns and idioms used in the
C# and .NET worlds, that would comply with the .NET Framework
Design Guidelines and would allow give developers all the
tools required to build full Cocoa applications.

We had two main requirements: the binding should just work
and the code should be MIT X11 licensed. For the binding to
just work, we turned to the .NET Framework Design Guidelines
book as it captures years of design decisions, programming
idioms and advise that would help C# and .NET developers. By
following the Design Guidelines we:

Avoid surprises

Blend with other C# and .NET libraries

Reduce the room for errors

Increase developer joy

Minimizes time for the developer to be productive

Every bit of existing .NET knowledge translates

Luckily for us, .NET was designed from the start to be an
interoperability framework. A framework that supports the
most advanced requirements to make multiple runtimes and
frameworks to communicate seamlessly with each other. We used
these features to create our bindings.

The above goals turned into the following technical
requirements:

Developers should be able to consume Cocoa APIs as C# APIs

Allow developers to subclass Objective-C classes

Subclass should work with C# standard constructs

Derive from an existing class

Call base constructor

Overriding methods should be done with C#'s override system

Do not expose developers to Objective-C selectors

Provide a mechanism to call arbitrary Objective-C libraries

Make common Objective-C tasks easy, and hard Objective-C tasks possible

Expose Objective-C properties as C# properties

Expose a strongly typed API, for example instead
of exposing the generic-container NSArray or
individual NSObjects. This means that developers
get a few benefits:

MonoDevelop can flag errors as you write
the code

MonoDevelop can present documentation
popups on types, methods, properties and
parameters as you type them.

Minimize runtime errors by catching
invalid casts at compile time.

Encourage in-IDE API exploration without
rebuilding, and without having to look up the
types in the documentation.

Turn int and uint parameters that should have been
enums as C# enumerations and C# enumerations with
[Flags] attributes

Expose the basic Foundation as C# native types:

NSString becomes string

NSArray becomes strongly-typed array

Events and notifications, give users a choice
between:

Support the Objective-C delegate pattern:

Strongly typed version is the default

Weakly typed version for advance
use cases

C# event system

Class libraries should be MIT X11 licensed, like the rest of Mono's class libraries.

Curated APIs: there is no point in binding every UNIX or
CoreFoundation C API available, as those are not very useful
in practice. Bind only those that are required to build
applications or get access to mandatory functionality.

More information about our API can be found here:
http://monotouch.net/Documentation/API_Design

Binding Cocoa

Cocoa consists of two sets of APIs, one set is an object
oriented C-callable API and another one is the Objective-C
based API.

C-based APIs were bound using a traditional P/Invoke
approach where the C-based API is wrapped in a C# class. This
includes APIs like AudioToolbx, CoreGraphics, CoreFoundation
and CoreText. There is very little magic in these bindings,
they are straight forward bindings, similar in spirit to what
you would do if you wrapped those APIs for C++ use. I am in
particular very proud of the much simpler AudioToolbox API.

The Objective-C APIs is where the UI heavy lifting takes
place and where most of the high-level functionality is found,
and this includes APIs like Foundation and AppKit. The
Objective-C APIs are bound using a new binding engine
(MonoMac.ObjCRuntime) and the btouch binding generator.

The btouch binding generator consumes an API contract in
the form of a C# source file and generates a binding that
matches the specified contract., for example, this is the API
definition for the NSActionCell:

We produced
a comprehensive
guide to binding Objective-C APIs with MonoTouch that
applies directly to MonoMac.

Since a lot of the work of binding an Objective-C API is
very repetitive, we have also included a header parser that
does most of the heavy lifting in producing the above API from
the Objective-C header file. The parser output then needs to
be then massaged a bit to produce a binding that satisfies our
design requirements. For example, NSArray arguments and
return types must be looked up on the documentation and the
proper strong typed inserted.

Status

Unlike MonoTouch, MonoMac is not a complete binding for all
of the Cocoa APIs at this point. This has been a weekend
effort for Geoff and myself but it has reached the point where
it can be used for building applications and it has reached
the point where we can start taking contributions to the
effort.

Currently MonoMac binds:

CoreFoundation (the parts that are needed, see the design principles)

CoreText (done)

CoreGraphics (done)

Foundation (the parts that are needed, and helper tools to support the rest)

AppKit (About 30% left to be done)

If you are interested in advancing the state of MonoMac, we
are currently looking for contributors to help us bind the
other Objective-C frameworks and help us complete AppKit.

Where we are going

MonoMac is merely the library that gives C# developers
access to the underlying APIs on OSX, it does not include the
tooling necessary to create a full application bundle.

Luckily, MonoDevelop has already most of the code needed in
the form of the MonoTouch plugin. We will update this plugin
to also support creating full application bundles for OSX.

A new feature that developers will be interested in is the
new "Mono bundler" tool that we are hoping we can include in
Mono 2.8. This bundler examines your .NET application and
generates an application bundle that contains both your
application code and any dependencies that it needs from Mono
in a self-contained package.

This is the technology being used by Banshee on OSX today.
The tool constructs a self-contained application based on your
system installed Mono that you can distribute to your users,
without requirement them to install Mono in the first place.

But we need your help. There are many small and
medium tasks that developers can help us with that will free
our already busy weekends and will allow us to have a full
MonoMac experience done in a shorter period of time.