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.
To get MonoMac, you need to get two modules from GitHub: monomac and maccore.
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:
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:
More information about our API can be found here: http://monotouch.net/Documentation/API_Design
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:
[BaseType (typeof (NSCell))] interface NSActionCell { [Export ("initTextCell:")] IntPtr Constructor (string aString); [Export ("initImageCell:")] IntPtr Constructor (NSImage image); [Export ("target")] NSObject Target { get; set; } [Export ("action")] Selector Action { get; set; } [Export ("tag")] int Tag { get; set; } }
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.
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:
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.
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.
The more help we get, the sooner this will be done.
We need contributors in the following areas:
Please join us on the mono-osx mailing list to discuss the future of MonoMac.
Update Currently this requires a preview Mono to work from http://mono.ximian.com/monobuild/preview/download-preview/
Posted on 19 Apr 2010