GTK Hello World in Six Different Languages

January 23rd, 2008

I’m still somewhat in holiday mode, so this entry is probably going to feel a little cheap for those of you following my more technical posts. I’m a big fan of GTK+ for user interfaces. If you don’t have the option or desire to use the Java platform and Swing, GTK+ is one of the better cross-platform user interface toolkits out there.

It’s high-level enough that it is easy to build quick, effective GUIs but low-level enough not to get in your way when you need to start messing around at the pixel level. GUIs can be built by hand using code, or designed using Glade and exported to an XML document to be loaded at runtime by any GTK+ binding. Currently it runs on Windows and Linux (the toolkit actually has its roots in GNOME) and has bindings for most popular programming languages. The only major downer is that Mac users are left out in the cold unless they go to the (herculean) effort of getting X11 up and running.

All the little differences between the various GTK+ bindings out there tend to get my goat when I move from one language to another. You would think that a GTK+ example in C could easily be translated to other languages without referencing documentation right? For one reason or another, the GTK+ bindings for other languages tend to diverge from the pleasant consistency of the C API to varying degrees. This post is all about those little differences that crop up even in the simplest applications: GTK’s take on “Hello World” in a few different languages.

C

C, being the language GTK+ is actually written in, is probably the most consistent with function naming across the different objects … the GTK_* and G_* macros are quite ugly though.

#include <gtk/gtk.h>

int main (int argc, char **argv) {
  GtkWidget *window;
  gtk_init(&argc, &argv);

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW (window), "Hello, World");
  g_signal_connect (G_OBJECT (window), "delete-event", gtk_main_quit, NULL);
  gtk_widget_show_all (window);

  gtk_main();
  return 0;
}

C#/Mono

GTK# adds stuff like the Application object and delegates to produce a “Hello World” example I had to go digging around in documentation for. Not too bad on the whole, though.

using Gtk;
using GtkSharp;

public class HelloWorld {
  public static void Main(string[] args) {
    Gtk.Window window = new Gtk.Window();
    window.Title = "Hello, World";
    window.DeleteEvent += delegate { Application.Quit(); };
    window.ShowAll();
    Application.Run();
  }
}

Ocaml

The Ocaml bindings diverge from the original C API much more so than the other languages listed here, most likely due to design decisions that had to be made to provide a C binding to a functional language. My only real grumble is the inconsistency with window#event#connect vs window#connect. I’m guessing there was a technical reason for that, but it still irks me every time I see it.

let delete_event evt = false

let destroy () = GMain.Main.quit ()

let main () =
  let window = GWindow.window in
  let _ = window#set_title "Hello, World" in
  let _ = window#event#connect#delete ~callback:delete_event in
  let _ = window#connect#destroy ~callback:destroy in
  let _ = window#show () in
  GMain.Main.main ()
;;

let _ = main () ;;

Perl

Although I find writing Perl to be painful for everything but processing text files in a terminal, I found the Perl GTK bindings to be relatively straightforward.

use strict;
use Gtk2 '-init';

my $window = Gtk2::Window->new;
$window->set_title("Hello, World");
$window->signal_connect('delete-event', sub { Gtk2->main_quit; });
$window->show_all;
Gtk2->main;

Python

I’m more familiar with PyGTK than with other bindings, so this was a snap. Why they chose GtkObject.connect over GtkObject.signal_connect is a mystery and the pygtk.require(’…’) crap is a little weird, but aside from that there should be nothing surprising here (this is a good thing!).

import pygtk
pygtk.require('2.0')
import gtk

window = gtk.Window()
window.set_title('Hello, World')
window.connect('delete-event', gtk.main_quit)
window.show_all()
gtk.main()

Ruby

RubyGNOME provides a GTK+ binding for Ruby. Take an almost 1:1 port of the C API, take away the ugly casting macros, mix in closures for handling signals and Ruby really is one of the nicest ways to get intimate with GTK+.

require 'gtk2'

window = Gtk::Window.new
window.title = 'Hello, World'
window.signal_connect(:delete-event) { Gtk.main_quit }
window.show_all

Gtk.main

That’s all for now. There are many more language bindings for GTK+ out in the wild for languages like Lisp/Scheme, C++, Haskell and Erlang. If you’re looking around for a GUI toolkit, be sure to give GTK a go. There’s plenty of documentation available for all the bindings listed here, often with some very detailed and easy to follow tutorials.

UPDATE: Miguel and she suggested some changes to the C#/Mono and RubyGNOME examples.
UPDATE 2: Aristotle suggested an easier way to initialize the Perl GTK bindings.

Categories: C, GTK, Ocaml, Python, Ruby, Software Development |

11 Comments

  1. schlenk

    How about adding gnocl (gtk/Tcl binding): http://www.dr-baum.net/gnocl/

  2. hannes

    that’s our hello world in Dylan. Also take a look at our gtk demo application (a TCP/IP stack with packet sniffer) at http://www.networknightvision.com/

    module: hello-world

    define frame ()
    keyword title: = “Hello, world”
    end;

    define function main()
    start-frame(make());
    end function main;

    // Invoke our main() function.
    main();

  3. nominolo

    In Haskell: http://reddit.com/r/programming/info/66e9b/comments/c02z7si
    (I didn’t know how put it as a comment without breaking indentation.)

  4. Paolo Bonzini

    GNU Smalltalk:

    GTK.Gtk gstGtkInit.
    w := GTK.GtkWindow new: GTK.Gtk gtkWindowToplevel.
    w title: ‘Hello, World’.
    w connectSignal: ‘destroy’
    to: [ :w :data | GTK.Gtk mainQuit ]
    selector: #value:value:
    userData: nil.
    w show.

  5. Mike Mol

    Very cool. Do you mind if I appropriate the code for Rosetta Code?

  6. she

    In the ruby version, Gtk.init is no longer needed (its only needed in older versions)

    Also I would recommend to use :delete_event instead of ‘delete-event’, to me it looks nicer (and you dont need to use the closing ‘ in this case as well)

  7. Miguel de Icaza

    Shorter C# version:

    Removes unnecessary helper routine, the Title is used in the constructor, but its useful to keep the explicit assignment to see a typical piece of C# code

    using Gtk;

    public class HelloWorld {
    public static void Main(string[] args) {
    Gtk.Window window = new Gtk.Window(”Hello World”);
    window.Title = “Hello, World”;
    window.DeleteEvent = delegate { Application.Quit (); };
    window.ShowAll();
    Application.Run();
    }
    }

  8. And Haskell too!

    http://www.haskell.org/gtk2hs/

  9. tom
    • schlenk: I’ll check out gnocl.
    • nominolo, Paolo, hannes: Thanks for your additional GTK examples!
    • Mike Mol: Of course, go nuts. :)
    • she, Miguel: Just included your suggestions. Thanks for the feedback!
  10. crc

    A version in Forth (RetroForth 9.2.10, using the optional GTK 2 bindings)

    ‘ bye is boot
    init
    window: hello
    hello ” Hello, World!” setTitle
    show: hello
    gtk_main

  11. Patrik

    The C example is (at least in my browser (Firefox Ubuntu)) not entirely complete since the include statement uses “less than” and “greater than” signs and the browser interprets these as html tags, *doh*

    Most people probably knows this and checks the source for the stuff to include, but just an improvement suggestion :)

    Great post all in all!
    cheers