Tuesday, July 29, 2008

Cocoa#, Mono and Me

My great application:

Currency Converter.net

Yeah, OK, not so great. But this Inverse Hoffman is the result of a couple of hours hacking in Mono, with Cocoa#. My app's largely based on the Stupid Word Counter tutorial, though it's a from-scratch implementation of the famous Apple/NeXT sample application in C#.

Firstly, a little history. My first encounter with .NET was back in about 2003 at a Microsoft Developer Roadshow in the car park (and later lecture theatre) in Oxford's comlab. I was particularly interested in their discussions of cross-platform capability, Project Rotor (I kept in touch with one of the Rotor developers) and so on, but really didn't see much exciting in .NET. Nonetheless, being a fair man, I took my beta CDs of Windows 2003 and Visual Studio .NET and gave them a whirl. Unfortunately, still not much interesting. Largely due to buggy betas and a lack of beta documentation.

Now accessing Cocoa from non-ObjC languages is nothing new, we've been doing it from Perl, Python, Ruby and Java for ages and partcularly old farts might even remember Objective-Tcl. Why should I care about Cocoa#? Well for a start, there are likely to be a lot Windows developers out there with some (language that boils down to MS IL eventually) skills who are wanting to produce Mac applications, and it'd be interesting to see what we'll end up with when they do. And it's always fun to learn a new language, anyway ;-)

Good points

  • Real NIB files. No really, that interface is genuinely an IB 3.x NIB based on the Cocoa Application template. The objects inside it are Objective-C objects, and there are good old outlets and actions (I haven't yet investigated whether Cocoa Bindings would work).

  • macpack. A command-line tool which takes your IL executable and wraps it up in a Cocoa application bundle, ready for drag-deployment.

  • Good inline bridging information. Unlike, say, PyObjC the language bridge isn't completely dynamic, but unlike the Java bridge or JIGS you don't have to keep a separate manual mapping of real classes onto ObjC shams. For instance, here's the controller from Currency Converter.net, complete with class, ivar and method exports:

namespace info.thaesofereode.CurrencyConverter
public partial class CurrencyConverterController : Cocoa.Object
public CurrencyConverterController(System.IntPtr native_object) : base(native_object) {}

//Cocoa IBOutlets
private Cocoa.TextField inputCurrency;
private Cocoa.TextField outputCurrency;
private Cocoa.TextField conversionRate;

//Cocoa IBAction
public void calculate(Cocoa.Object sender)
//get the rate from the view
System.String rate = conversionRate.Value;
CurrencyConverterModel.Rate = System.Convert.ToDouble(rate);
//get the currency
System.String input = inputCurrency.Value;
System.Double output = CurrencyConverterModel.convert(System.Convert.ToDouble(input));
//update the UI
outputCurrency.Value = System.Convert.ToString(output);

Bad points

  • Not very Cocoa-like wrapper classes. I think this is deliberate; they've gone for making the Cocoa shim look like a .NET interface because after all, we're programming from .NET. This is a bit disappointing as I'm more familiar with PyObjC and the Perl-ObjC-Bridge where the APIs are left pointedly alone, but given the target audience of Cocoa# it's unsurprising.

  • MonoDevelop. Luckily, using it isn't mandated.

So, overall, one more good point than bad (and a tentative two, if you overlook MonoDevelop); a pretty good initial evaluation and I might give this a deeper scrape.

1 comment:

Jack said...

See NObjective bridge. It provides unique set of features with extra-high performance