NAME

Gtk2::api - Mapping the Gtk+ C API to perl

ABSTRACT

The Gtk2 module attempts to stick as close as is reasonable to the C API, to minimize the need to maintain documentation which is nearly a copy of the C API reference documentation. However, the world is not perfect, and the mappings between C and perl are not as clean and predictable as you might wish. Thus, this page described the basics of how to map the C API to the perl API, and lists various points in the API which follow neither the C API documentation nor the mapping principles.

DESCRIPTION

FIXME The list of specific differences is not complete.

The canonical documentation is the C API reference at http://developer.gnome.org/doc/API/gtk/ and http://developer.gnome.org/doc/API/gdk/

There are two main sections: 'BINDING BASICS' describes the principles on which the bindings work; understanding these can lead you to guess the proper syntax to use for any given function described in the C API reference. The second section lists various specific points of difference which don't necessarily correspond with what you expect; this section is in three main parts: missing methods, renamed methods, and different call signatures.

BINDING BASICS

Anything listed as "deprecated" in the C API reference does not appear in the bindings. Many functions refer to C concepts which are alien to the bindings. many things have replacements.

Namespaces and Objects

The namespaces of the C libraries are mapped to perl packages according to scope, although in some cases the distinction may seem rather arbitrary:

g_ => Glib  (the Glib module - distributed separately)
gtk_ => Gtk2
gdk_ => Gtk2::Gdk
gdk_pixbuf_ => Gtk2::Gdk::Pixbuf
pango_ => Gtk2::Pango

Objects get their own namespaces, in a way, as the concept of the GType is completely replaced in the perl bindings by the perl package name. This goes for GBoxed, GObject, and even things like Glib::String and Glib::Int (which are needed for specifying column types in the Gtk2::TreeModel). (Flags and enums are special -- see below.)

GtkButton => Gtk2::Button
GdkPixbuf => Gtk2::Gdk::Pixbuf
GtkScrolledWindow => Gtk2::ScrolledWindow
PangoFontDescription => Gtk2::Pango::FontDescription

With this package mapping and perl's built-in method lookup, the bindings can do object casting for you. This gives us a rather comfortably object-oriented syntax, using normal perl syntax semantics:

in C:
  GtkWidget * b;
  b = gtk_check_button_new_with_mnemonic ("_Something");
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b), TRUE);
  gtk_widget_show (b);

in perl:
  my $b = Gtk2::CheckButton->new ('_Something');
  $b->set_active (1);
  $b->show;

You see from this that constructors for most widgets which allow mnemonics will use mnemonics by default in their "new" methods. For those who don't guess this right off, Gtk2::Button->new_with_mnemonic is also available. Cast macros are not necessary, and your code is a lot shorter.

Flags and Enums

Constants are handled as strings, because it's much more readable than numbers, and because it's automagical thanks to the GType system. Constants are referred to by their nicknames; basically, strip the common prefix, lower-case it, and optionally convert '_' to '-':

GTK_WINDOW_TOPLEVEL => 'toplevel'
GTK_BUTTONS_OK_CANCEL => 'ok-cancel' (or 'ok_cancel')

Flags are a special case. You can't (sensibly) bitwise-or these string-constants, so you provide a reference to an array of them instead. Anonymous arrays are useful here, and an empty anonymous array is a simple way to say 'no flags'.

FOO_BAR_BAZ | FOO_BAR_QUU | FOO_BAR_QUUX => [qw/baz quu qux/]
0 => []

In some cases you need to see if a bit is set in a bitfield; the best thing i can think of for that is

in C:
 /* event->state is a bitfield */
 if (event->state & GDK_CONTROL_MASK)
         g_printerr ("control was down\n");

in perl:
 # $event->state is a reference to an array of flag constants
 warn "control was down\n"
     if grep {/control-mask/} @{ $event->state };

FIXME if anyone can think of a better way to check this, i'm all ears.

The gtk stock item stuff is a little different -- the GTK_STOCK_* constants are actually macros which evaluate to strings, so they aren't handled by the mechanism described above; you just specify the string, e.g., GTK_STOCK_OK => 'gtk-ok'. The full list of stock items can be found at http://developer.gnome.org/doc/API/2.0/gtk/gtk-Stock-Items.html

Memory Handling

The functions for ref'ing and unref'ing objects and free'ing boxed structures are not even mapped to perl, because it's all handled automagically by the bindings. I could write a treatise on how we're handling reference counts and object lifetimes, but all you need to know as perl developer is that it's handled for you, and the object will be alive so long as you have a perl scalar pointing to it or the object is referenced in another way, e.g. from a container.

Miscellaneous

In C you can only return one value from a function, and it is a common practice to modify pointers passed in to simulate returning multiple values. In perl, you can return lists; any functions which modify arguments have been changed to return them instead. A common idiom in gtk is returning gboolean, and modifying several arguments if the function returns TRUE; for such functions, the perl wrapper just returns an empty list on failure.

in C:  foo_get_baz_and_quux (foo, &baz, &quux);
in perl:  ($baz, $quux) = $foo->get_baz_and_quux;

Most things that take or return a GList, GSList, or array of values will use native perl arrays (or the argument stack) instead.

You don't need to specify string lengths, although string length parameters should still be available for functions dealing with binary strings. You can always use substr to pass different parts of a string.

Anything that uses GError in C will croak on failure, setting $@ to the returned error message. The ideology here is that GError is to be used for runtime exceptions, and croak is how you do that in perl. You can catch a croak very easily by wrapping the function in an eval:

eval { $pixbuf = Gtk2::Gdk::Pixbuf->new_from_file ($filename); };
if ($@) {
     # couldn't open the file, $@ has the message
} else {
     # do something with $pixbuf
}

This has the added advantage of letting you bunch things together as you would with a try/throw/catch block in C++ -- you get cleaner code.

Use normal perl callback/closure tricks with callbacks. The most common use you'll have for callbacks is with the Glib signal_connect method:

$widget->signal_connect (event => \&event_handler, $user_data);
$button->signal_connect (clicked => sub { warn "hi!\n" });

Note that the $user_data is optional, and with perl closures, you don't often need it.

A major change from gtk-perl (the bindings for Gtk+-1.x) is that callbacks take their arguments in the order proscribed by the C documentation, and only one value is available for user data. gtk-perl allowed you to pass multiple values for user_data, and always brought in the user_data immediately after the instance reference; this proved to be rather confusing, and did not follow the C API reference, so we decided not to do that for gtk2-perl.

MISSING METHODS

g_object_ref => no replacement
g_object_unref => no replacement
g_boxed_free => no replacement

The bindings do automatic memory management. You should never need to use these.

gtk_timeout_add => Glib::Timeout->add
gtk_timeout_remove => Glib::Source->remove
gtk_idle_add => Glib::Idle->add
gtk_idle_remove => Glib::Source->remove
gtk_input_add => Glib::IOChannel->add_watch
gtk_input_remove => Glib::Source->remove

The gtk_* functions are deprecated in favor of the g_* ones. Gtk2::Helper has a wrapper for Glib::IOChannel->add_watch which makes it behave more like gtk_input_add.

gtk_accel_group_from_accel_closure => no replacement

Because of the use of Perl subroutine references in place of GClosures, there is no way to preserve at the Perl level the one-to-one mapping between GtkAccelGroups and GClosures. Without that mapping, this function is useless.

RENAMED METHODS

gtk_aspect_frame_set => $aspect_frame->set_params

Avoid a clash with $gobject->set.

DIFFERENT CALL SIGNATURES OR SEMANTICS

As a general rule function that take a pair of parameters, a list and the number of elements in that list, will normally omit the number of elements and just accept a variable number of arguments that will be converted into the list and number of elements. In many instances parameters have been reordered so that this will work. See below for exceptions and specific cases.

Gtk2::ItemFactory::create_items

The n_entries parameter has been ommited and callback_data is accepted as the first parameter. All parameters after that are considered to be entries.

Gtk2::List::insert_items

Position and items parameters flipped order so that an open ended parameter list could be used. $list->insert_items($position, $item1, $item2, ...) (Note that GtkList and GtkListItem are deprecated and only included because GtkCombo still makes use of them, they are subject to removal at any point so you should not utilize them unless absolutely necessary.)

Gtk2::TreeModel::get

If no column idexes are passed all columns are returned as an array. This is a slight deviation from the C api that can be easily implemented in the wrappers and may be useful. If you don't know it's there it should in no way effect the behavior of the function.

Gtk2::TreeSelection::get_selected

Since most of the time you are interested only in the iter, this function behaves differently in scalar context than in list context:

## scalar context
$iter = $tree_selection->get_selected;
## list context
($model, $iter) = $tree_selection->get_selected;
Gtk2::TreeSelection::get_selected_rows

Returns @paths; model is not returned as documented in the C API. to get the model, try $selection->get_tree_view->get_model.

Gtk2::Widget::path
Gtk2::Widget::class_path

In C, these functions return the length of the strings, the path string, and the reverse path string. In perl, the string length is unnecessary, and has been omitted from the return list.

($path, $path_reverse) = $widget->path;
($path, $path_reverse) = $widget->class_path;
Gtk2::Gdk::Colormap::alloc_colors

Whereas alloc_color only takes one color, alloc_colors takes an array of colors; the colors are thus moved to the end on the vectorized version. alloc_colors returns a list containing a boolean status value for each color passed in, telling whether the color could be allocated.

# single
$gdkcolormap->alloc_color ($color, $writeable, $best_match)
@s = $gdkcolormap->alloc_colors ($writable, $best_match, @colors)

Note that $colormap->free_colors (@colors) is used to deallocate colors allocated by alloc_color/alloc_colors, and has nothing to do with memory management. therefore, you may need to call free_colors.

Gtk2::Style::paint_polygon

The list of coordinates for the vertices was moved to the end to use the argument stack.

$style->paint_polygon ($gdkwindow, $state_type, $shadow_type,
                       $area, $widget, $detail, $fill,
                       $x1, $y1, $x2, $y2, ...);
Gtk2::AccelGroup::connect
Gtk2::AccelGroup::disconnect

Where a GClosure is wanted by the C stuff, a perl subroutine reference suffices. However, because of this, there are a few subtle differences in sematics. a GClosure may be connected to only one GtkAccelGroup; however, a perl subroutine may be connected to many GtkAccelGroups (because at the binding level, a new GClosure is created on each call to ->connect). Thus, $accel_group->disconnect will disconnect the first group it finds to be connected to the given perl subroutine. To disconnect all groups attached to a subroutine, you can call disconnect with the same subroutine reference (or name) until it stops returning true.

Gtk2::TreePath->new_from_indices

Unlike its C counterpart, this function does not need a -1 to terminate the list of index values; in fact, it will croak on negative numbers with a friendly reminder. Although this function was introduced into gtk+ in 2.2.0, it is available in gtk2-perl with gtk+ 2.0.x.

SEE ALSO

The canonical documentation is the C API reference at http://developer.gnome.org/doc/API/gtk/ and http://developer.gnome.org/doc/API/gdk/

There should be a similar document for Glib --- link to it here when it exists.

AUTHOR

muppet <scott at asofyet dot org>