Writing Object-Oriented Code with GLib/GObject

Having written code in various languages, from BASIC to Pascal to C++, I have settled on C as the language I will use to write the computer language that I want to create. C presents both advantages and disadvantages; the biggest disadvantage, for those spoiled by object-oriented programming as I have been, is that C provides no direct language support for object-oriented constructs. For reasons that deserve a rant of their own, I will not use C++; nor again will I use Objective-C even though I liked it right up to the point that those responsible for the GCC implementation of the language began to dumb down the interfaces in an attempt to conform with Apple's idea of what the language should be. Perhaps that, too, will someday find a rant of its own -- but not now.

So, that leaves C.

Object-Oriented Programming in C

Although C does not directly support object-oriented programming, it is possible to use the language for such a purpose -- really, any procedural language can be so used. I found one notable example (PDF) of this usage in my searches, although it is rather old: it adds some syntax elements to support object-oriented programming constructs and relies on a custom preprocessor to reduce that syntax into basic C. While such an approach undoubtedly works, the structure of the syntax presented is a little off-putting to me, if only because I have strong ideas with regard to how code should look. Besides, C already has a powerful preprocessor -- why not use that?

Someone has. Their approach is advantageous in that the object-oriented constructs do not require any separate libraries, and the author has provided for virtually every feature that programmers have come to expect from object-oriented programming environments. However, once again, the structure of the syntax is a little off-putting to me.

To my mind, the syntax used to produce objects and classes should flow from the natural syntax of the language itself; consequently, the two above examples -- and even Objective-C -- do not really satisfy my desire for clean code because their syntax is an imposition upon the underlying language. In reality, that is exactly what the majority of today's object-oriented programming environments are: object-oriented features laid on top of a procedural language. It would be nice to find a language that was built with object-orientation in mind; that incorporates the constructs directly into its syntax (this is the reason I want to write a computer language, incidentally, but more on that later). Failing that, the object-oriented syntax should at least integrate well with the code using it. Unfortunately, the two above examples do not quite hit the mark. I do not say this by way of criticism, because both work well. Such an opinion is a subjective one, derived from my own personal aesthetic sense. You are free to disagree.

The author of the second object-oriented C programming example above refers to GLib, which is a library included with the GTK+ Project. I've been following GTK+ ever since I first started using Linux and GNOME, and while I understand that many people have a love-hate relationship with the project (and with GNOME), I like GTK+ and, to a lesser extent, GNOME 2. (The topic of GNOME 3 is another one of those self-contained rants). Why do I like it? It is one of the only well-formed, well-written, and well-documented APIs that I have found in my years of programming. Leaving aside the questions of whether the higher-level API (GTK+) dumbs down interface design too much, the core libraries (GLib, GObject, and GIO) provide a large number of features in a well-documented and consistent way. Moreover, GObject provides object-oriented programming for C -- and it does so in a way that works well with the code that uses it.

Object-Oriented Programming Using GObject

This is not to suggest that constructing classes and objects with GObject is perfect. Most likely the first complaint that you will have when attempting to use GObject is the tedious nature of defining your own classes and objects: first you have to define the instance structure, then the class structure, then the support macros; if you want to use the properties system, you have to define the properties enumeration and the getter and setter routines; if you are adopting an interface, you must define the interface initialization method -- and so forth. Some of the tedium has to do with the fact that you must code things that are done by the compiler in "actual" object-oriented programming languages, but the writers of GObject have defined a few macros in an attempt to mediate some of this. Another contributing factor is the need to conform to the conventions established by the authors of GObject.

When I first started programming with GObject, I quickly grew tired of the monotony. I liked the conventions, because they ensure that code remains consistent, but there had to be a better way to make use of GObject. Why did the authors only define a few macros, when the C preprocessor is powerful enough to automate much of the grunt work for us? In desperation, I looked at GOB, but found the syntax and need for additional project files (one file for each object) off-putting. Instead, I decided to expand upon the macros created by the GObject authors, tweaking them until I was satisfied with the results. By using the C preprocessor to its utmost, I was able to hide much of the grunt work required to define classes and objects while still conforming to the majority of the conventions established by the authors of GObject.

Next: Using glib-utility.h