DMP Photo Booth: Going All In With GLib Primitives
While working on DMP Photo Booth, I’ve been trying to use GLib library calls as often as possible as opposed to standard library calls. Why? Portability, of course. I’ve been doing my best to ensure my application is as portable as possible. While doing this, I find myself having to work with lots of glib types. After a few weeks of this, I find myself wondering if I shouldn’t be using these in my own code…
GLib defines g[type] versions of all standard C primitives, plus a few extras. The GLib reference manual describes these as falling into 4 different categories:
- New types which are not part of standard C (but are defined in various C standard library header files) – gboolean, gsize, gssize, goffset, gintptr, guintptr.
- Integer types which are guaranteed to be the same size across all platforms – gint8, guint8, gint16, guint16, gint32, guint32, gint64, guint64.
- Types which are easier to use than their standard C counterparts – gpointer, gconstpointer, guchar, guint, gushort, gulong.
- Types which correspond exactly to standard C types, but are included for completeness – gchar, gint, gshort, glong, gfloat, gdouble.
Let’s talk about these.
The new types represent boolean values, and size types. Both of these may have been new when GLib defined them, but they’ve since found their way into the C standard library since C99. That said, these are types that we often neglect to use. Who can honestly say they’ve never used a bare integer when a size_t would have been appropriate?
I feel that these are all good types to use, when needed. Maybe they no longer solve a real problem since C99, but GLib still uses them. I will use these for consistency’s sake, but the standard library types should suffice.
As we should all know, integers are not guaranteed to be the same size across different platforms. On platform A, an int may be 2 bytes, and on platform B, it may be 4 bytes. Meanwhile, these types provide this guarantee. Like the new types, C99 brings these types also, but in my opinion gint8 is easier to type than int_8.
Aside from ease, GLib uses its types, and for consistency I will too.
Types That Are “Easier To Use”
In my opinion, this one is debatable. The people over at Gnome may think that gpointer “looks better” and is “easier to use”, but I find it incredibly confusing. I’ve even mentioned this in past posts. Gpointer is a typedef of
void *. In other words, where you may have done this before:
void * foo = malloc(sizeof(foo));
…you would now do this:
gpointer foo = g_malloc(sizeof(foo))
…and now you’re left with this
gpointer foo;. Aside from the fact that it has the word “pointer” in the type name, this doesn’t look like a pointer. Even worse is when you see
gpointer * bar;. At first glance, this looks like it should be a
void * bar;, but it’s actually
void * * bar;. I know I’ve spent more time than I care to admit trying to figure out why
bar->the_bar was throwing compiler errors.
Maybe it’s just amateur hour in the DMP Undersea Laboratory, but I like to see the *. That way it’s right in my face that I’m dealing with a pointer. I can also count the number of *s to see how many array indices I’m dealing with. If I see
void *** super_foo; I know I’m dealing with a 3 dimensional array just by counting the stars. I don’t have to think about it. On the other hand if I see
gpointer ** super_foo; I have to know what gpointer is a typedef of; I can’t just trust my instincts.
For this reason, I will not be using gpointer or gconstpointer. The rest of the “easier to use” types can stay though.
Types That Correspond Exactly
There is not much to say about these. These types exist just for consistency’s sake. If you’re using GLib primitives, you should use these as well for consistency’s sake.
Seems Kind Of Pointless…
At first glance, yes it does. I must admit that while I was typeing this up, I wavered. “If all the GLib types are in the standard library in C99, why bother?” I thought. None of these types are objectivly better than the standard library versions, it’s just another name to remember. So why should we care?
The answer is because not all compilers/platforms support C99. The most nobale offender here is Microsoft Visual Studio. To quote Herb Sutter: “Our primary goal is to support “most of C99/C11 that is a subset of ISO C++98/C++11.”” This allegedly includes “C99 preprocessor and library extensions”, but this requires compiling with Visual Studio’s C++ compiler and accepting all the baggage that C++ brings. If you want to keep your code pure C, then you are stuck using C90 only.
So, long story short: if you want easy portability to Windows, consider using GLib primitives.
It is time to get with the program. Development of DMP Photo Booth is still early-enough along that a refactor to use GLib primitives won’t be too difficult. I will not change the API for the modules because, while I will most likely use GLib with the reference modules, I don’t want to impose a requirement to use GLib. Int and char are exactly equivilent to gint and gchar, so this should not cause any issues.
However, moving forward, I’ll be using GLib primitives.