Perl scripts often live in the terminal or deep inside a server handing out webpages or whatnot, but they don't have to stay there. Earlier, in chapter 2, we demonstrated using system libraries on Windows to display a simple MessageBox. This time, we turn to Linux (and BSDs with a desktop environment).

The libnotify library allows applications to send pop-up notifications to the user. These are the bubbles you see from apps like Slack, Discord, or your system updater.

Notifications from Affix!

This library uses the GLib object system (GObject), which is notoriously complex to bind manually. However, if we only want to trigger a notification, we can treat the objects as opaque pointers and ignore the internal complexity entirely.

The Recipe

use v5.40;
use Affix;

# 1. Find the library
# locate_lib searches system paths (like /usr/lib) for libnotify.so
# It returns the full path as a string.
my $libnotify = Affix::locate_lib('notify');
unless ($libnotify) {
    die "Could not find libnotify. Are you on Linux with libnotify-bin installed?";
}

# 2. Bind the lifecycle functions
# bool notify_init(const char *app_name);
affix $libnotify, 'notify_init',   [String] => Bool;
affix $libnotify, 'notify_uninit', []       => Void;

# 3. Bind the object functions
# NotifyNotification* notify_notification_new(const char *summary, const char *body, const char *icon);
affix $libnotify, 'notify_notification_new', [ String, String, String ] => Pointer [Void];

# bool notify_notification_show(NotifyNotification *notification, GError **error);
affix $libnotify, 'notify_notification_show', [ Pointer [Void], Pointer [Void] ] => Bool;

# 4. Use it
# Initialize the library with our app name
notify_init('Affix');

# Create the notification object
# We get back a Pin (opaque pointer), but we don't need to look inside it.
my $n = notify_notification_new(
    'Keep your stick on the ice! 🏒',                          #
    "Hello from Affix!\nWelcome to the fun world of FFI.",    #
    'dialog-information'                                      # Standard icon name
);

# Show it
# We pass undef for the second argument (GError**), meaning "ignore errors".
notify_notification_show( $n, undef );

# Clean up
notify_uninit();

How It Works

Kitchen Reminders