I just learned about vapigen to build a Vala .vapi interface from gobject introspection. Unfortunately it seems that through the way of g-ir-scanner some information gets lost and gir cannot transmit information such as the semantics of arrays (null-terminated or with length, etc.). I played with a “metadata” file for an hour (as described upstream), but it seems to be ignored entirely.

So for now I committed a manually adjusted vapi for gudev. This now makes it easy to write code that queries and listens to udev in Vala.

Small example:

using GUdev;

void
print_device(GUdev.Device d)
{
    stdout.printf("%s → %s\n", d.get_device_file(), d.get_sysfs_path());
    foreach (string s in d.get_device_file_symlinks())
        stdout.printf("  link: %s\n", s);
}

void
on_uevent(GUdev.Client client, string action, GUdev.Device dev)
{
    stdout.printf("[%s] ", action);
    print_device(dev);
}

int main(string[] args)
{
    var uc = new GUdev.Client({"usb"});

    print_device(uc.query_by_device_file(args[1]));

    stdout.printf("---- all block devices ---\n");
    GLib.List devs = uc.query_by_subsystem("block");
    foreach (GUdev.Device d in devs)
        print_device(d);

    stdout.printf("---- usb events ---\n");
    uc.uevent.connect(on_uevent);
    new GLib.MainLoop().run();
    return 0;
}

Build with valac --pkg gudev-1.0 udev.vala, and perhaps specify --vapidir if you keep the gudev-1.0.vapi file somewhere locally.

Update: I reverted the commit upstream for now, since Vala 0.8 already ships a gudev vapi. I must have overlooked that when I played with vapigen.. In the long run it’s probably better to generate vapis in the projects themselves to avoid API skew, but as long as the vapi can’t be generated automatically it does not make sense to have it in udev. Above code was updated for the vala provided one (which is lacking a return type specification for query_by_subsystem()).