It's always annoyed me that one has to write an XS module just to obtain these. It's a lot of extra work and bother, for something that ought to be so simple. So instead, I started thinking about it, how can I make this much simpler from Perl?
What I came up with is ExtUtils::H2PM; a module to make it trivially-easy to write this sort of boring module to wrap some constants and structures from OS's header files.
As a brief example, consider the following
use ExtUtils::H2PM;
module "Fcntl";
include "fcntl.h";
constant "O_RDONLY";
write_output $ARGV[0];
This is it. This is all the code you, as a module author, have to write. You store that in some file, lets call it Fcntl.pm.PL. You let the build system go about converting that into Fcntl.pm; which on my system now looks like this:
package Fcntl;
# This module was generated automatically by ExtUtils::H2PM from -e
push @EXPORT_OK, 'O_RDONLY';
use constant O_RDONLY => 0;
1;
This is a plain standard Perl module that can be installed and used, to provide that constant.
We can also create pack/unpack-style functions to wrap structure types too. Consider
use ExtUtils::H2PM;
module "Time";
include "time.h";
structure "struct timespec",
members => [
tv_sec => member_numeric,
tv_nsec => member_numeric,
];
write_output $ARGV[0];
For this we obtain:
package Time;
# This module was generated automatically by ExtUtils::H2PM from -e
use Carp;
push @EXPORT_OK, 'pack_timespec', 'unpack_timespec';
sub pack_timespec
{
@_ == 2 or croak "usage: pack_timespec(tv_sec, tv_nsec)";
my @v = @_;
pack "q q ", @v;
}
sub unpack_timespec
{
length $_[0] == 16 or croak "unpack_timespec: expected 16 bytes";
my @v = unpack "q q ", $_[0];
@v;
}
1;
This was done entirely automatically too.
In a real use-case, you'd be using this to wrap things like socket option constants/structures, and so on; cases where existing Perl functions wrap existing syscalls, you simply want to provide new option values or structures. I've now written several modules mostly or entirely relying on ExtUtils::H2PM to build them, freeing me of having to write all that XS code to implement them.