Skip to main content

If you don't have an IBM ID and password, register here.

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. This profile includes the first name, last name, and display name you identified when you registered with developerWorks. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

GNOMEnclature: Getting ready for GNOME 2, Part 2

Introducing GObject

Daniel Robbins (drobbins@gentoo.org), President/CEO, Gentoo Technologies, Inc.
Residing in Albuquerque, New Mexico, Daniel Robbins is the President/CEO of Gentoo Technologies, Inc., the creator of Gentoo Linux, an advanced Linux for the PC, and the Portage system, a next-generation ports system for Linux. He has also served as a contributing author for the Macmillan books Caldera OpenLinux Unleashed, SuSE Linux Unleashed, and Samba Unleashed. Daniel has been involved with computers in some fashion since the second grade, when he was first exposed to the Logo programming language as well as a potentially dangerous dose of Pac Man. This probably explains why he has since served as a Lead Graphic Artist at SONY Electronic Publishing/Psygnosis. Daniel enjoys spending time with his wife, Mary, and their daughter, Hadassah. You can contact Daniel at drobbins@gentoo.org.

Summary:  In this second installment of the newly relaunched "GNOMEnclature" column, relative GNOME newbie and "Common threads" columnist Daniel Robbins takes a look at the new Glib object system from a new GNOME developer's perspective. By the end of this article, you'll know enough about GNOME to decide if you want to try it for yourself (even if you are a stalwart C fan).

Date:  01 Jun 2002
Level:  Introductory

Comments:  

OOP programming in C?

In this article, we're going to take a look at the Glib object system, also called "GObject", which up until recently used to be part of GTK+. But before taking a look at the new object system in Glib 2.0, we need to address a more fundamental issue -- what exactly is an "object system" and why does it exist? After all, isn't C a non-object oriented language? It is possible to write object-oriented programs in C, or must one use C++ instead?

The answer is that it is possible to write object-oriented programs in C. However, because the concept of object isn't a part of the C language specification, an external library is required to provide this support. In this article, we use the term "object system" to describe a library that provides the foundation required for OOP programming, and Glib is an example of such a library. Glib provides a C implementation of classes, inheritance, reference counting, signals, interfaces, and object properties. By using Glib, C programmers can write object-oriented programs with ease.

So, it is possible to write object-oriented programs in C. However, you may be wondering why the GTK+ developers didn't just go ahead and use C++ instead. Without covering every possible explanation, here are a few reasons why it makes sense to have an object system for C. For one, there are many developers who simply prefer C to C++. In other situations, using a C++ compiler may not be an option due to project or platform constraints. Whatever the reason, having an object system for C opens up OOP programming (and GNOME programming, in particular) to a wider number of potential developers, and for that we're grateful.

C++ wrappers

That being said, all those C++ fanatics out there shouldn't be worried -- you can write GNOME programs in C++ too. Since C++ is a superset of the C language, you can easily combine C-style Glib/GTK+ code with your existing C++ projects. Alternatively, you can use a Glib/GTK+ C++ wrapper instead. A Glib/GTK+ C++ wrapper will allow you to interact with Glib objects using native C++ classes and objects.


Looking at GObject

Okay, so now you know what an object system is and what it's used for. Now, we'll take a look inside the Glib object system and explore some foundational GObject programming concepts. Up until recently, the GObject system was implemented in the GTK+ 1.2.x library. Now, with the imminent release of GTK+ 2, the object system has been moved down one layer to the new Glib 2 library. Thanks to this move, the Glib object system is now completely independent of GUI-related trappings. This is great news for those of us who would like to use classes and objects in non GTK+-based programs such as console-based applications and tools.

Now, let's see what the Glib object system (also called "GObject") looks like in comparison to the object system of C++ and the Java language. First, let's do a syntax comparison. In C++, you'd invoke a method via an object pointer as follows:

object->function(arg_a, arg_b);

Using a C++ object reference, you'd type:

object.function (arg_a, arg_b);

The Java language only has references, not pointers. The Java method call syntax is identical to a C++ referenced object method call:

object.function (arg_a, arg_b);

In contrast, GObject uses standard C function call syntax. The object pointer is passed as the first argument to the function. Also note that the function name is prefixed with the class name in order to prevent namespace collisions:

classname_function (object, arg_a, arg_b);

You may be wondering exactly how calling a GObject method differs from calling a simple C function. Well, from the perspective of the C programming language itself, there is no difference. As far as your C compiler is concerned, it is simply calling a function, and the first argument of that function happens to be a pointer to a standard C structure.

So your C compiler doesn't even know that we are writing an object-oriented program. However, don't let this fact fool you into thinking that GObject OOP programming is just a bunch of hokey technojargon for good old-fashioned C programming. GObject does do a lot of stuff behind the scenes, allowing you to create subclasses of existing classes, interfaces to classes (which we will discuss later in this article) and more. Yet all this OOP functionality has been designed to be fully compatible with standard C programming constructs.

Here's another important thing to know about GObject method calls. When passing the object to a class function (when you're invoking a method), you need to cast the object to match the expected type of the function you're calling. For example, if you have a GtkButton object that you want to pass to a function that takes a GtkWidget argument, you would write:

gtk_widget_show (GTK_WIDGET (button));

GObject interfaces

In addition to the many improvements to GObject, Glib 2 introduces an OOP concept called "interfaces." To understand what interfaces are, let's look at an example.

Let's say that we wanted to create a Pegasus object for an application. Since a pegasus is a mythological winged horse, the natural OOP thing to do would be to create a new Pegasus class that uses the Horse class as its parent. Then, we could add the necessary code to our new class to support "wings." In this case, creating Pegasus as a subclass of Horse makes sense because it expresses a relationship between the two classes.

However, let's say we had a variety of unrelated classes, such as Horse, Car, and House, and we wanted to make it possible for all of them to talk. This new ability has nothing to do with their relationship to one another -- in fact, these three classes are not related in any way that is meaningful to us. Yet we want all of them to support new abilities related to talking. What would we do?

Interfaces provide a solution to this problem, allowing us to add common capabilities to disparate classes. So going back to the example above, we could simply write a "Talk" interface for the Horse, Car, and House classes. Suddenly, our three unrelated classes are "talk-enabled" and are able to work with new talk-related functions that we create. And these new talk-related functions happily interact with our objects by using the "Talk" interface themselves. So, thanks to interfaces, our three unrelated classes now speak the same language.

In Glib, you can create any number of interfaces for a class. So, if we created a Talk interface for our House class, we could define a say() function as follows:

void say (Talk *mytalk, const char *myphrase);

Then, we could call the say() function, casting our myhouse variable to the "Talk" interface:

say (TALK(myhouse), "hello there!");

A more down-to-earth, authentic example of interfaces can be found in the GtkEditable interface in GTK+ 2 (see Resources for a link). Both the text widget and the entry widget implement this interface.


GObject signals

Generally, event-driven GUI programs consist of one main loop. In this loop, the program continually waits for new messages to be sent from the X server. These messages, called events, are interpreted by the program, and allow the program to respond to the user selecting a menu item, clicking on a button, and so on.

Signals are a lot like events, except that they connect objects to one another. They allow objects to automatically "react" to changes in the state of another object without requiring an explicit event loop. The signal of one object simply needs to be connected to the method of another. Then, when the first object "emits" the signal (due to an internal change in state), the second object "catches" this change and reacts appopriately. No event loop is needed because signals are implemented using callbacks -- the emission of a signal simply results in a C function being called. Signals are the efficient and flexible glue that tie the objects in your program together.

In fact, if you look at the previous GNOMEnclature column, you'll see that we had quite a few example code lines that looked like this:

g_signal_connect (G_OBJECT (window), "destroy", gtk_main_quit, NULL);

In the above code snippet, we connect the "destroy" signal of our main window object to the gtk_main_quit() function. Thanks to g_signal_connect(), when our window emits a "destroy" signal (when the window is closed), our program will automatically quit. If you've ever done any event-driven programming in the past, I think you'll find signals to be a refreshing change from the common practice of setting up an explicit event processing loop.

So, we've seen how to connect a signal to a standard C function. But how would we connect this same signal to the method of a particular object? Easy -- simply use the following template:

g_signal_connect (G_OBJECT (window), "destroy", classname_function, object);

Simply replace classname_function with the method to be called, and replace object with the object pointer upon which the method should operate. To learn more about signals, check out the Resources section of this article for some good links.

However, note that Glib and GTK+ 2.0 bring some changes to the area of signals. While the underlying concepts haven't changed, the signal system has been moved from GTK+ 2.0 to Glib. This has the handy side-effect of making it possible to use signals in non-GUI applications. If you are writing new GNOME 2.0 code, you should use Glib's new GSignal class; GTK+ 2.0 signals are still around, but simply consist of a "wrapper" that uses Glib's GSignal behind the scenes.

Despite all the changes, Glib signals (prefixed by g_signal_) are generally very similar to their GTK+ counterparts (which are prefixed by gtk_signal_). However, if you've created or are planning to create your own custom signals, you should read the GObject GSignal reference documentation (see Resources) to catch up on some of the changes that may apply to you.

Conclusion

Now that we've taken a look at GObject fundamentals, you should be equipped with the necessary fundamental concepts to begin your GNOME programming career. I'll see you in the next "GNOMEnclature" column, as we continue our preparation for the GNOME 2 platform. See you then!


Resources

About the author

Residing in Albuquerque, New Mexico, Daniel Robbins is the President/CEO of Gentoo Technologies, Inc., the creator of Gentoo Linux, an advanced Linux for the PC, and the Portage system, a next-generation ports system for Linux. He has also served as a contributing author for the Macmillan books Caldera OpenLinux Unleashed, SuSE Linux Unleashed, and Samba Unleashed. Daniel has been involved with computers in some fashion since the second grade, when he was first exposed to the Logo programming language as well as a potentially dangerous dose of Pac Man. This probably explains why he has since served as a Lead Graphic Artist at SONY Electronic Publishing/Psygnosis. Daniel enjoys spending time with his wife, Mary, and their daughter, Hadassah. You can contact Daniel at drobbins@gentoo.org.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in

If you don't have an IBM ID and password, register here.


Forgot your IBM ID?


Forgot your password?
Change your password


By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. This profile includes the first name, last name, and display name you identified when you registered with developerWorks. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)


By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Linux, Open source
ArticleID=11222
ArticleTitle=GNOMEnclature: Getting ready for GNOME 2, Part 2
publish-date=06012002
author1-email=drobbins@gentoo.org
author1-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).