ExtUtils::H2PM(3pm)
πΈ ExtUtils::H2PM π
okay bestie, so this is the perl docs for ExtUtils::H2PM, from the User Contributed Perl Documentation section β and it's lowkey one of the most useful little build-time tools out there. no cap. let's get into it. β¨
π NAME
"ExtUtils::H2PM" β it automatically generates perl modules that wrap C header files. that's the whole vibe. iconic behaviour honestly. π
π¦ DESCRIPTION
okay so picture this: you want to wrap some system functionality β think socket() types, or ioctl() calls β and the only interesting bits you actually care about are, like, the values of some constants, or the layouts of structures that basically only the C header files know about. π
so normally you'd be like "ugh, guess i have to write an entire XS module just to hold some constants and pack/unpack functions" β but NO. not with this module, bestie. this lets the author generate, at module build time, a pure perl module containing constant declarations and structure utility functions. and the slay part? the resulting module needs no XS module loaded at run time. pure perl, no cap. π
and like, compared to h2ph, "C::Scan::Constants", and so on β this module does it a completely different way. it generates a small C program stuffed with printf() lines that spit out the values of the constants, compiles it, and runs it. that means it can operate without needing tricky syntax parsing or guessing at what's inside the C header files. no vibes-based guesswork here, just facts. β¨
it can also automatically build pack/unpack functions for simple structure layouts, where all the members are simple integer fields or character array fields. but β and this is important β it is not meant as a full replacement for arbitrary code you'd write in XS modules. if your structures contain pointers, or need special custom handling, you're probably gonna need to write an XS module. sorry bestie, that's just the truth. π
π₯ FUNCTIONS
β module
module $name;
sets the name of the perl module to generate. it'll slap a "package" header on there for you. π
π include
include $file;
adds a file to the list of headers that the C program will include, so it can grab the constants or structures from it. π«Ά
π constant
constant $name, %args;
adds a numerical constant. simple as that.
the following additional named arguments are also recognised:
name => STRINGβ use this given name for the generated constant function. if you don't specify it, the C name for the constant gets used instead.ifdef => STRINGβ if present, guard the constant with an"#ifdef STRING"preprocessor macro. and if that given string isn't defined? no constant gets generated. periodt. β¨
π structure
structure $name, %args;
adds a structure definition. this one requires a named argument called "members". that should be an ARRAY ref containing an even number of name-definition pairs. the first of each pair should be a member name, and the second should be one of the structure member definitions listed below. π
the following additional named arguments are also recognised:
pack_func => STRINGunpack_func => STRINGβ use the given names for the generated pack or unpack functions.with_tail => BOOLβ if true, the structure is a header with more data behind it. the pack function takes an optional extra string value for the data tail, and the unpack function will return an extra string value containing it. πno_length_check => BOOLβ if true, the generated unpack function will not first check the length of its argument before attempting to unpack it. so if the buffer isn't long enough to unpack all the required values, the remaining ones just won't be returned. this may be useful, for example, in cases where various versions of a structure have been designed β later versions adding extra members β but where the exact version found may not be easy to determine beforehand. πarg_style => STRINGβ defines the style in which the functions take arguments or return values. it defaults to"list", which takes or returns a list of values in the given order. the other allowed value is"hashref", where the pack function takes a HASH reference and the unpack function returns one. each will consist of keys named after the structure members. and if a data tail is included, it will use the hash key of"_tail". π¦ifdef => STRINGβ if present, guard the structure with an"#ifdef STRING"preprocessor macro. if the given string is not defined, no functions will be generated. π
the following structure member definitions are allowed:
member_numericβ the field contains a single signed or unsigned number. its size and signedness will be automatically detected. πmember_strarrayβ the field contains a NULL-padded string of characters. its size will be automatically detected. πΈmember_constant($code)β the field contains a single number, same as for"member_numeric". but instead of consuming/returning a value in the arguments list, this member will be packed from an expression, or asserted that it contains the given value. the string$codewill be inserted into the generated pack and unpack functions, so it can be used for constants generated by the"constant"directive. π
so the structure definition results in two new functions being created: "pack_$name" and "unpack_$name", where $name is the name of the structure β with the leading "struct" prefix stripped off. these behave similarly to the familiar functions such as "pack_sockaddr_in": the "pack_" function takes a list of fields and returns a packed string, and the "unpack_" function takes a string and returns a list of fields. iconic. π
π no_export, use_export, use_export_ok
no_export;
use_export;
use_export_ok;
these control the export behaviour of the generated symbols:
"no_export"creates symbols that are not exported by their package β you gotta use them fully-qualified. π"use_export"creates symbols that are exported by default."use_export_ok"creates symbols that are exported if they're specifically requested at"use"time.
the mode can be changed at any time, and it will only affect the symbols that follow it. it defaults to "use_export_ok". β¨
π§ gen_output
$perl = gen_output;
returns the generated perl code. this is used internally for testing purposes, but normally you wouldn't need it β see instead "write_output". π«Ά
π« write_output
write_output $filename;
write the generated perl code into the named file. this would normally be used as the last function in the containing script, to generate the output file. in the case of "ExtUtils::MakeMaker" or "Module::Build" invoking the script, the path to the file to be generated should be given in $ARGV[0]. so normally, therefore, the script would end with:
write_output $ARGV[0];
that's the move. π
π include_path
include_path $path
adds an include path to the list of paths used by the compiler. simple, but essential. β
π₯ define
define $symbol;
define $symbol, $value;
adds a symbol to be defined on the compiler's commandline, by using the "-D" option. this is sometimes required to turn on particular optional parts of the included files. you can also specify an optional value. no cap. π
β¨ EXAMPLES β¨
Okay bestie, so normally this module isn't the one doing stuff at runtime β it's the little build-time gremlin that some other module drags in while it's being built, so it can construct the relevant constants and structure functions straight out of the system headers. Very "behind the scenes, still iconic" energy. π
So like, imagine your OS defines a brand new type of socket. It's got its own packet and address families, maybe some new socket options that only work on this socket. We can build a module holding the relevant constants and structure functions by writing something like this:
#!/usr/bin/perl
use ExtUtils::H2PM;
module "Socket::Moonlaser";
include "moon/laser.h";
constant "AF_MOONLASER";
constant "PF_MOONLASER";
constant "SOL_MOONLASER";
constant "MOONLASER_POWER", name => "POWER";
constant "MOONLASER_WAVELENGTH", name => "WAVELENGTH";
structure "struct laserwl",
members => [
lwl_nm_coarse => member_numeric,
lwl_nm_fine => member_numeric,
];
write_output $ARGV[0];
Now β if we save this script as, say, lib/Socket/Moonlaser.pm.PL, then when the distribution gets built, the script runs and generates the contents of the file lib/Socket/Moonlaser.pm. Once it's installed, literally any other code can just go
use Socket::Moonlaser qw( AF_MOONLASER );
and boom, constant imported. π
But hmm, the method above doesn't leave us any room to actually include other code in the module. π Like maybe, alongside those simple constants, we want functions, documentation, etc. To make that work, name the script something like lib/Socket/Moonlaser_const.pm.PL instead β that way that is the name used for the generated output. Then the code can live inside the real lib/Socket/Moonlaser.pm (which is just a normal perl module) like this:
package Socket::Moonlaser;
use Socket::Moonlaser_const;
sub get_power
{
getsockopt( $_[0], SOL_MOONLASER, POWER );
}
sub set_power
{
setsockopt( $_[0], SOL_MOONLASER, POWER, $_[1] );
}
sub get_wavelength
{
my $wl = getsockopt( $_[0], SOL_MOONLASER, WAVELENGTH );
defined $wl or return;
unpack_laserwl( $wl );
}
sub set_wavelength
{
my $wl = pack_laserwl( $_[1], $_[2] );
setsockopt( $_[0], SOL_MOONLASER, WAVELENGTH, $wl );
}
1;
Sometimes the actual C structure layout just does not match the semantics we want to present to perl modules using this extension wrapper. Classic. π Socket address structures typically carry their address family as the first member, but that detail isn't exposed by, like, the sockaddr_in and sockaddr_un functions. To handle that, the low-level structure packing and unpacking functions can be generated with a different name, and then wrapped in higher-level functions in the main code. For example, in Moonlaser_const.pm.PL:
no_export;
structure "struct sockaddr_ml",
pack_func => "_pack_sockaddr_ml",
unpack_func => "_unpack_sockaddr_ml",
members => [
ml_family => member_numeric,
ml_lat_deg => member_numeric,
ml_long_deg => member_numeric,
ml_lat_fine => member_numeric,
ml_long_fine => member_numeric,
];
This generates a pack/unpack function pair that takes or returns five arguments β and those functions will not be exported. Then in our main Moonlaser.pm file we can wrap them to actually expose a different API:
sub pack_sockaddr_ml
{
@_ == 2 or croak "usage: pack_sockaddr_ml(lat, long)";
my ( $lat, $long ) = @_;
return _pack_sockaddr_ml( AF_MOONLASER, int $lat, int $long,
($lat - int $lat) * 1_000_000, ($long - int $long) * 1_000_000);
}
sub unpack_sockaddr_ml
{
my ( $family, $lat, $long, $lat_fine, $long_fine ) =
_unpack_sockaddr_ml( $_[0] );
$family == AF_MOONLASER or croak "expected family AF_MOONLASER";
return ( $lat + $lat_fine/1_000_000, $long + $long_fine/1_000_000 );
}
Sometimes a structure contains members which are themselves structures. Nested. Very meta, very slay. πΈ Suppose a different definition of that address, which at the C layer looks like:
struct angle
{
short deg;
unsigned long fine;
};
struct sockaddr_ml
{
short ml_family;
struct angle ml_lat, ml_long;
};
We can instead flatten this structure tree to get those five fields, by naming the sub-members of the outer structure:
structure "struct sockaddr_ml",
members => [
"ml_family" => member_numeric,
"ml_lat.deg" => member_numeric,
"ml_lat.fine" => member_numeric,
"ml_long.deg" => member_numeric,
"ml_long.fine" => member_numeric,
];
π¦ TODO π¦
- Consider more structure members. With strings comes the requirement to have members that store a size. This requires cross-referential members. And while we're at it it might be nice to have constant members; fill in constants without consuming arguments when packing, assert the right value on unpacking.
π AUTHOR π
Paul Evans <leonerd@leonerd.org.uk>
and that's the whole page, bestie!! π«Ά this came out of ExtUtils::H2PM(3pm) under perl v5.42.0, dated 2025-07-25. go forth and generate some headers, no cap πβ¨
π¦ where this page comes from
- fedora 43: perl-ExtUtils-H2PM 0.11-8.fc43 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms