The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

GError Exception Objects

GError is a facility for propagating run-time error / exception information around in C, which is a language without native support for exceptions. GError uses a simple error code, usually defined as an enum. Since the enums will overlap, GError includes the GQuark corresponding to a particular error "domain" to tell you which error codes will be used. There's also a string containing a specific error message. The strings are arbitrary, and may be translated, but the domains and codes are definite.

Perl has native support for exceptions, using eval as "try", croak or die as "throw", and if ($@) as "catch". $@ may, in fact, be any scalar, including blessed objects.

So, GPerl maps GLib's GError to Perl exceptions.

Since, as we described above, error messages are not guaranteed to be unique everywhere, we need to support the use of the error domains and codes. The obvious choice here is to use exception objects; however, to support blessed exception objects, we must perform a little bit of black magic in the bindings. There is no built-in association between an error domain quark and the GType of the corresponding error code enumeration, so the bindings supply both of these when specifying the name of the package into which to bless exceptions of this domain. All GError-based exceptions derive from Glib::Error, of course, and this base class provides all of the functionality, including stringification.

All you'll really ever need to do is register error domains with gperl_register_error_domain, and throw errors with gperl_croak_gerror.

void gperl_register_error_domain (GQuark domain, GType error_enum, const char * package)

Tell the bindings to bless GErrors with error->domain == domain into package, and use error_enum to find the nicknames for the error codes. This will call gperl_set_isa on package to add "Glib::Error" to package's @ISA.

domain may not be 0, and package may not be NULL; what would be the point? error_enum may be 0, in which case you'll get no fancy stringified error values.

SV * gperl_sv_from_gerror (GError * error)

You should rarely, if ever, need to call this function. This is what turns a GError into a Perl object.

gperl_gerror_from_sv (SV * sv, GError ** error)

You should rarely need this function. This parses a perl data structure into a GError. If sv is undef (or the empty string), sets *error to NULL, otherwise, allocates a new GError with g_error_new_literal() and writes through error; the caller is responsible for calling g_error_free(). (gperl_croak_gerror() does this, for example.)

void gperl_croak_gerror (const char * ignored, GError * err)

Croak with an exception based on err. err may not be NULL. ignored exists for backward compatibility, and is, well, ignored. This function calls croak(), which does not return.

Since croak() does not return, this function handles the magic behind not leaking the memory associated with the #GError. To use this you'd do something like

 PREINIT:
   GError * error = NULL;
 CODE:
   if (!funtion_that_can_fail (something, &error))
      gperl_croak_gerror (NULL, error);

It's just that simple!

SYNOPSIS

  eval {
     my $pixbuf = Gtk2::Gdk::Pixbuf->new_from_file ($filename);
     $image->set_from_pixbuf ($pixbuf);
  };
  if ($@) {
     print "$@\n";
     if (Glib::Error::matches ($@, 'Gtk2::Gdk::Pixbuf::Error',
                                   'unknown-format')) {
        change_format_and_try_again ();
     } elsif (Glib::Error::matches ($@, 'Glib::File::Error', 'noent')) {
        change_source_dir_and_try_again ();
     } else {
        # don't know how to handle this
        die $@;
     }
  }

DESCRIPTION

Gtk2-Perl translates GLib's GError runtime errors into Perl exceptions, by creating exception objects based on Glib::Error. Glib::Error overloads the stringification operator, so a Glib::Error object will act like a string if used with print() or warn(), so most code using $@ will not even know the difference.

The point of having exception objects, however, is that the error messages in GErrors are often localized with NLS translation. Thus, it's not good for your code to attempt to handle errors by string matching on the the error message. Glib::Error provides a way to get to the deterministic error code.

You will typically deal with objects that inherit from Glib::Error, such as Glib::Convert::Error, Glib::File::Error, Gtk2::Gdk::Pixbuf::Error, etc; these classes are provided by the libraries that define the error domains. However, it is possible to get a base Glib::Error when the bindings encounter an unknown or unbound error domain. The interface used here degrades nicely in such a situation, but in general you should submit a bug report to the binding maintainer if you get such an exception.

The source line and file closest to the emission of the exception, in the same format that you'd get from croak() or die().

If there's non-ascii characters in the filename Perl leaves them as raw bytes, so you may have to put the string through Glib::filename_display_name for a wide-char form.

The error message. This may be localized, as it is intended to be shown to a user.

The error domain. You normally do not need this, as the object will be blessed into a corresponding class.

The enumeration value nickname of the integer value in $error->code, according to this error domain. This will not be available if the error object is a base Glib::Error, because the bindings will have no idea how to get to the correct nickname.

This is the numeric error code. Normally, you'll want to use value instead, for readability.

Throw an exception with a Glib::Error exception object. Equivalent to croak (Glib::Error::new ($class, $code, $message));.

Create a new exception object of type $class, where $class is associated with a GError domain. $code should be a value from the enumeration type associated with this error domain. $message can be anything you like, but should explain what happened from the point of view of a user.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 478:

Unknown directive: =forapidoc