login
Allan Hsuimeem VIP - Click to find out more
blog post Universal Truths and Cycles
Posted in the monoland diaries on May 02, 2006 at 3:01 AM

Today's imeemĀ OS X client release marks our first universal binary release, as well as our first Mac release to include external IM service support.

I think we may be the first people to ship a universal Mono, thanks to Bryan's work. I find it amazing that we were able to fit all the imeem client dependencies, including a universal build of Mono and most of the GAC, into a 10MB disk image.

Of course, with the new universal binary and inclusion of external IM support, the OS X client has more moving parts than ever. If you run into anything weird, please let us know.



blog post PDC 2005
Posted in the monoland diaries on Sep 27, 2005 at 4:03 PM

I know I'm late to this particular party, but here are some things that happened at PDC:

Sessions
We attended a few interesting sessions (mostly regarding the .NET CLR), but a lot of the coverage was on technology that isn't going to come out until Windows Vista is released (or even later). This was a little frustrating; it felt like somebody was constantly waving technology in our faces and saying "Look how much better this is than the crap you have to deal with!" and then quickly pulling it away, saying, "ha ha, suckers!" It's nice to see that Microsoft is working to improve the APIs that we have to deal with, but I wish there were more sessions on things that we could use, you know, now. I got a little tired of hearing things like "Don't use this code here; we'll have an API for you to do things when we ship." One of the coolest things about WWDC (the Apple equivalent of PDC) was that all of the technologies covered in the sessions were actually available for use in shipping applications. I wish there had been more of that at PDC. I just couldn't get too excited over things that we couldn't, say, ship in next week's imeem revision. That being said, Atlas and LINQ looked pretty promising, though I could see people abusing the new C# language features that come with LINQ in terrible ways.

Speaking to Developers
Probably the most satisfying time we spent was talking to the Microsoft developers that worked on Windows Forms and IE7. If IE7 includes support for CSS3 border-radius or multiple background support, it may be partially due to Dustin's prodding.

Mono
We showed Jackson and Miguel from Novell/Ximian/Mono the OS X client running on our Powerbooks using Mono. They seemed to like how we were using Mono and we talked a bit about Dumbarton. Hopefully this will lead to imeem being a little more involved with Mono development. I think we may try to contribute Dumbarton to Mono sooner than I had previously thought.



blog post Wretched, retching on all fours.
Posted in the monoland diaries on Sep 12, 2005 at 2:06 AM

I'll be in LA all week with Dustin and Dalton, attending PDC.

Los Angeles, I'm Yours.



blog post Still verging... or something.
Posted in the monoland diaries on Sep 05, 2005 at 5:50 AM

Many of the employees here at imeem are Mac users. For some time, we'd all been talking about an OS X port of imeem, but with our limited resources, we weren't able to divert much time from Windows development towards this end.

Sometime around the beginning of this summer, Bryan Berg and I started really getting down into the details of bringing imeem to the Mac. We'd been wrapping our heads around it for a while (Bryan more than I), but we hadn't done much concrete implementation. Most of the Windows imeem client is written in C# .NET, with a good amount of abstraction between the UI and the rest of the client.

We wanted to write the Mac UI with Cocoa because we wanted the end product to feel like a genuine Mac application regardless of what was going on under the covers. We knew we would have to use Mono in some fashion; we weren't about to rewrite the imeem backend. With these things in mind, we entered:

The Forest of Fear, Uncertainty, and Infuriatingly Weird Bugs: Cocoa#
If you read my last post about Dumbarton, you may wonder why we didn't use Cocoa#. Well, we tried. If you are unfamiliar with Cocoa#, using it involves running a code generator on OS X frameworks in order to produce .cs files that you can then use to call Objective-C code from C#. There are also some facilities to call C# from Objective-C. Bryan had written a simple client using only C# and the Cocoa# generated bindings, but it didn't look like it was going to work out. Writing a Cocoa application in C# was incredibly unholy at times and it didn't seem like Cocoa# was really ready for us to use. Being in the early stages of development, Cocoa# had decent support for some of the Cocoa Appkit, but some things just don't work right yet. The auto-generated code for a lot of Core Foundation was often hilariously wrong/weird.

We spent a couple weeks of hard hackery on a hybrid approach, where we wrote the UI layer in Objective-C and compiled it into a framework. We used Cocoa# to load the framework and execute the UI, as well as pass information back and forth. This approach ultimately ended in tears; sometimes Cocoa# just didn't work right. For example, to instantiate an NSNumber with the integer value 5 in C#, I had to do something like this:

NSNumber someNumber = new NSNumber(5); //this doesn't actually set the value.
someNumber = someNumber.initWithInt(5); //this sets the value.

If you're familiar with Objective-C, you'll notice the alloc/init pattern. Graaaah. I have no clue how the above code plays with the retain/release memory management semantics of Objective-C/Cocoa. I don't really want to know. Debugging showed that the second assignment would actually assign someNumber to a different object than the one returned by the constructor. Also, you can forget about creating more than one NSNumber with the same value. That causes Cocoa# to crash.

After our experience with Cocoa#, we decided that we needed something simpler and more sane. We decided to roll our own solution, and to build:

The Bridge Over the Stinky Salt Marsh: Dumbarton
Using the Mono embedded C API, we built an OS X framework that works quite differently from Cocoa#. Its focus is on calling managed code from unmanaged code; though the opposite is entirely possible. Our approach is a lot less "magic" than Cocoa#; it requires more work by the developer, but is also quite a bit more lightweight.

To make calls into native code from managed code, we use the System.Runtime.CompilerServices namespace to mark our methods as internal calls and then use Dumbarton to register native function pointers for each method at runtime. To make calls from Objective-C into C#, we wrote classes that work to make method invocation easy and painless (at least relative to the raw embedded Mono API). So far, we've written these features (some of which I mentioned in my last post):
1. Objective-C representations of C# classes and objects that allow property getting/setting and method invocation (mostly intended for subclassing by the developer).
2. Mapping between the Cocoa/Objective-C retain/release model of memory management and the mono garbage collector.
3. Translation of C# exceptions into NSExceptions for method invocation, so that @try/@catch/@finally works for C# exceptions.
4. A series of class categories for easy conversion back and forth between common types (ie: NSString<->MonoString, NSData<->MonoArray)
5. An NSThread poser that makes it safe to call into the managed runtime from threads started using Cocoa. This helps particularly for threads created by code outside of the developer's control. More on this later.
6. Utility subclasses of the representations mentioned in part 1 for common C# interfaces (IList, ArrayList, etc).
7. Macros for boxing/unboxing value types.

Right now, the shared library for Dumbarton.framework compiles down to about 40k of code, sans debugging symbols.

Eventually, I'd like to get Dumbarton contributed back to Mono, but it's not at the top of our priorities right now. Before we ship an OS X client, we still have to figure out how we'll deal with our Mono dependency, which will be the subject of a later post...



blog post On The Verge
Posted in the monoland diaries on Sep 02, 2005 at 7:23 PM

If you've been wondering what's been going on with the OS X port of imeem:

We currently have a client in development running under OS X. We use an embedded mono runtime instance to run the backend. The UI is being written in Objective-C. Bryan Berg and I wrote a bridging framework to facilitate communication between C# and ObjC.

We call the ObjC<->C# bridging framework Dumbarton, named after the bridge that spans the San Francisco Bay between Fremont and Menlo Park. Our Reasoning: both bridges are somewhat unpleasant to cross, but they get you where you want to go. (Ever tried driving across the Dumbarton with your windows open?)

The framework tries to make it easy to bring up an embedded runtime and call managed code from native code (and vice-versa). It also takes care of various caveats that come along with the whole managed<->native craziness. Some examples:
1. Mapping between the ObjC retain/release model of memory management and the mono garbage collector.
2. Translation of C# exceptions into NSExceptions down at the invocation layer so that ObjC @try/@catch/@finally works with C# method calls.

I'll post more later on our rationale behind writing Dumbarton and why we're building imeem for OS X this way.



blog post Boxing's been good to me, Howard.
Posted in the monoland diaries on Aug 18, 2005 at 6:35 PM

Here are some tips I've learned the hard way regarding the C API for embedding mono:

1. Method invocations always return objects of type MonoObject*; value types will require unboxing.

2. Method arguments are always pointers. Never pass anything by value. Value types should *not* get boxed when passed into a method invocation unless you're passing an value type in as an Object argument (ie: ArrayList.Add).

3. Value type arguments marked with the out keyword seem to be passed in the same way normal value types (by reference, no boxing). I'm unsure of Object arguments (I haven't had to do anything that awesome yet), but I suspect they need to be passed as MonoObject**.

Fun times.




RssFeed