Thursday, May 29, 2008

GMime 2.3.0

GMime 2.3.0 has been released which marks the first development release of GMime since 2002. A new age has begun.

This new development release gets rid of off_t from all public interfaces, replacing them with gint64 instead so that there is no API/ABI breakage when building it with Large File support. But more importantly (to me), it also fixes a number of the API inconsistencies/uglyness that I discovered while looking over the GMime-Sharp bindings.

The GMime-Sharp bindings still have a long way to go to be beautiful, but they are becoming more of a priority as I am more interested in using GMime-Sharp myself. If you are a user of the GMime-Sharp bindings, I'd love for you to try out GMime 2.3.0 and give me some feedback and how to improve the API even more. I, myself, will continue to scrutinize the API and make adjustments as I go - in the end, I hope to have the most beautiful MIME .NET API ever created.

At first, I was only going to fix GMime's public interfaces to use gint64 instead of off_t and save the rest of my changes for a "3.0" or at least a "2.6", but I decided that since I was breaking the ABI anyway - I might as well do some cleanup and I think developers worldwide will thank me after their initial pain of porting their software to the new API (for which I hope to write a script to help in their troubles).

Largely these changes are renaming of functions, sometimes shuffling them to become methods on a base class, etc.

I got rid of GMimePartEncodingType and created a GMimeContentEncoding enum instead, complete with a g_mime_content_encoding_to_string() and g_mime_content_encoding_from_string(). I also created a new state object called GMimeEncoding (may rename to GMimeEncoder?) which simplifies the base64/QuotedPrintable/UU encoder/decoder APIs a little in that it handles initializing the state variables for you as you encode or decode to any of those encodings.

As I was updating code to use these new enums/structs, I was able to simplify GMimeFilterBasic to not need its own GMimeFilterBasicType struct - instead, you pass the encoding and a bool to encode vs decode to the new g_mime_filter_basic_new() constructor. This has helped simplify a lot of code inside GMime and I'm sure it will help simply everyone elses code as well, because there is no longer a need to map GMIME_PART_ENCODING_BASE64 to GMIME_FILTER_BASIC_TYPE_BASE64_ENC or GMIME_FILTER_BASIC_TYPE_BASE64_DEC.

I've also fixed GMimeContentType and GMimeContentDisposition to notify their parent GMimeObject when they are changed so that the following C#ism becomes possible:

part.ContentType.SetParameter ("name", "fubar.txt");

Previously, you'd have to use the GMimeObject's Content-Type helper methods instead of using the Content-Type's methods directly, like so:

part.SetContentTypeParameter ("name", "fubar.txt");

There are quite a few other improvements like this that I've added to the GMime-Sharp API as well. Sure, they may be minor, but they make the API much more polished.


Sankar said...


Alexander Larsson said...

Dude, you need to use goffset (in recent glib) instead of gint64.

Joe Shaw said...

AFAIK Beagle is the only consumer of the gmime-sharp bindings, although things may have changed in the last year or so.

I'd suggest taking a look at how Beagle uses it, most notably the mail filter here:

and the Evolution mail backend here:

Hope this helps!

Jeffrey Stedfast said...

Thanks Joe - my guess is that Beagle is also probably the only consumer of GMime-Sharp so far - but that may change, so I might as well try to make the API suck less ;)

Looks like Beagle doesn't use the sucky parts of the API, so it probably won't be affected except for maybe a few slight changes.

InternetAddressList.ParseString() - should this maybe be renamed to InternetAddressList.Parse()? Would that be more consistent with .NET's APIs?

Alex: any reason to use goffset over gint64? Only reason I'm using gint64 right now is that my glib does not have goffset and I figure if mine doesn't, then it is unlikely that my target audience will have it.

Honestly, I'd also like to kep the GLib requirement for GMime as old as possible (configure currently checks for >= 2.0.0 but I might need 2.2, but afaik, I don't need anything newer than that currently so it seems silly to bump the requirement to GLib-2.14, just for goffset.

Alexander Larsson said...

goffset is always just:

typedef gint64 goffset;

so, gint64 works as good as goffset. However imho using goffset is nicer as a documentation aspect.

Jeffrey Stedfast said...

oh, yes, with that I'd agree ;-)

Code Snippet Licensing

All code posted to this blog is licensed under the MIT/X11 license unless otherwise stated in the post itself.