File Coverage

blib/lib/ExtUtils/H2PM.pm
Criterion Covered Total %
statement 191 223 85.6
branch 50 80 62.5
condition 8 14 57.1
subroutine 33 35 94.2
pod 14 17 82.3
total 296 369 80.2


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2010-2023 -- leonerd@leonerd.org.uk
5              
6             package ExtUtils::H2PM 0.11;
7              
8 10     10   606458 use v5.14;
  10         124  
9 10     10   51 use warnings;
  10         19  
  10         282  
10              
11 10     10   56 use Carp;
  10         24  
  10         619  
12              
13 10     10   62 use Exporter 'import';
  10         20  
  10         754  
14             our @EXPORT = qw(
15             module
16             include
17             constant
18              
19             structure
20             member_numeric
21             member_strarray
22             member_constant
23              
24             no_export use_export use_export_ok
25              
26             gen_output
27             write_output
28              
29             include_path
30             define
31             );
32              
33 10     10   5250 use ExtUtils::CBuilder;
  10         826299  
  10         560  
34              
35 10     10   94 use List::Util 1.39 qw( pairs ); # ->key
  10         284  
  10         36196  
36              
37             =head1 NAME
38              
39             C - automatically generate perl modules to wrap C header files
40              
41             =head1 DESCRIPTION
42              
43             This module assists in generating wrappers around system functionallity, such
44             as C types or C calls, where the only interesting features
45             required are the values of some constants or layouts of structures normally
46             only known to the C header files. Rather than writing an entire XS module just
47             to contain some constants and pack/unpack functions, this module allows the
48             author to generate, at module build time, a pure perl module containing
49             constant declarations and structure utility functions. The module then
50             requires no XS module to be loaded at run time.
51              
52             In comparison to F, C, and so on, this module works
53             by generating a small C program containing C lines to output the
54             values of the constants, compiling it, and running it. This allows it to
55             operate without needing tricky syntax parsing or guessing of the contents of
56             C header files.
57              
58             It can also automatically build pack/unpack functions for simple structure
59             layouts, whose members are all simple integer or character array fields.
60             It is not intended as a full replacement of arbitrary code written in XS
61             modules. If structures should contain pointers, or require special custom
62             handling, then likely an XS module will need to be written.
63              
64             =cut
65              
66             my $output = "";
67              
68             my @preamble;
69             my @fragments;
70              
71             my $done_carp;
72              
73             my @perlcode;
74             my @genblocks;
75              
76             my $export_mode; use_export_ok();
77             my @exports; my @exports_ok;
78              
79             =head1 FUNCTIONS
80              
81             =cut
82              
83             sub push_export
84             {
85 26     26 0 183 my $name = shift;
86              
87 26 100       271 if( $export_mode eq "OK" ) {
    50          
88 23         112 push @exports_ok, $name;
89             }
90             elsif( $export_mode ) {
91 0         0 push @exports, $name;
92             }
93             }
94              
95             =head2 module
96              
97             module $name;
98              
99             Sets the name of the perl module to generate. This will apply a C
100             header.
101              
102             =cut
103              
104             my $modulename;
105             sub module
106             {
107 18     18 1 29482 $modulename = shift;
108              
109 18 50       181 $output .= gen_perl() if @fragments;
110              
111 18         260 $output .= "package $modulename;\n" .
112             "# This module was generated automatically by ExtUtils::H2PM from $0\n" .
113             "\n";
114              
115 18         77 undef $done_carp;
116             }
117              
118             =head2 include
119              
120             include $file;
121              
122             Adds a file to the list of headers which will be included by the C program, to
123             obtain the constants or structures from
124              
125             =cut
126              
127             sub include
128             {
129 18     18 1 346 my ( $file, %params ) = @_;
130              
131             # undocumented but useful for testing
132 18 50       104 if( $params{local} ) {
133 18         139 push @preamble, qq[#include "$file"];
134             }
135             else {
136 0         0 push @preamble, "#include <$file>";
137             }
138             }
139              
140             # undocumented so far
141             sub perlcode
142             {
143 0     0 0 0 my ( $code ) = @_;
144 0         0 push @perlcode, $code;
145             }
146              
147             =head2 constant
148              
149             constant $name, %args;
150              
151             Adds a numerical constant.
152              
153             The following additional named arguments are also recognised:
154              
155             =over 4
156              
157             =item * name => STRING
158              
159             Use the given name for the generated constant function. If not specified, the
160             C name for the constant will be used.
161              
162             =item * ifdef => STRING
163              
164             If present, guard the constant with an C<#ifdef STRING> preprocessor macro. If
165             the given string is not defined, no constant will be generated.
166              
167             =back
168              
169             =cut
170              
171             sub constant
172             {
173 9     9 1 88 my $constname = shift;
174 9         62 my %args = @_;
175              
176 9   66     103 my $name = $args{name} || $constname;
177              
178 9         71 push @fragments, qq{ printf("$constname=%ld\\n", (long)$constname);};
179              
180 9 100       40 if( my $symbol = $args{ifdef} ) {
181 1         16 $fragments[-1] = "#ifdef $symbol\n$fragments[-1]\n#endif";
182             }
183              
184             push @genblocks, [ $constname => sub {
185 9     9   104 my ( $result ) = @_;
186 9 100       123 return () unless defined $result;
187              
188 8         239 push_export $name;
189 8         168 "use constant $name => $result;";
190 9         127 } ];
191             }
192              
193             =head2 structure
194              
195             structure $name, %args;
196              
197             Adds a structure definition. This requires a named argument, C. This
198             should be an ARRAY ref containing an even number of name-definition pairs. The
199             first of each pair should be a member name. The second should be one of the
200             following structure member definitions.
201              
202             The following additional named arguments are also recognised:
203              
204             =over 4
205              
206             =item * pack_func => STRING
207              
208             =item * unpack_func => STRING
209              
210             Use the given names for the generated pack or unpack functions.
211              
212             =item * with_tail => BOOL
213              
214             If true, the structure is a header with more data behind it. The pack function
215             takes an optional extra string value for the data tail, and the unpack
216             function will return an extra string value containing it.
217              
218             =item * no_length_check => BOOL
219              
220             If true, the generated unpack function will not first check the length of its
221             argument before attempting to unpack it. If the buffer is not long enough to
222             unpack all the required values, the remaining ones will not be returned. This
223             may be useful, for example, in cases where various versions of a structure
224             have been designed, later versions adding extra members, but where the exact
225             version found may not be easy to determine beforehand.
226              
227             =item * arg_style => STRING
228              
229             Defines the style in which the functions take arguments or return values.
230             Defaults to C, which take or return a list of values in the given order.
231             The other allowed value is C, where the pack function takes a HASH
232             reference and the unpack function returns one. Each will consist of keys named
233             after the structure members. If a data tail is included, it will use the hash
234             key of C<_tail>.
235              
236             =item * ifdef => STRING
237              
238             If present, guard the structure with an C<#ifdef STRING> preprocessor macro.
239             If the given string is not defined, no functions will be generated.
240              
241             =back
242              
243             =cut
244              
245             sub structure
246             {
247 10     10 1 83 my ( $name, %params ) = @_;
248              
249 10         157 ( my $basename = $name ) =~ s/^struct //;
250              
251 10   66     125 my $packfunc = $params{pack_func} || "pack_$basename";
252 10   66     82 my $unpackfunc = $params{unpack_func} || "unpack_$basename";
253              
254 10         28 my $with_tail = $params{with_tail};
255 10         27 my $no_length_check = $params{no_length_check};
256              
257 10   100     65 my $arg_style = $params{arg_style} || "list";
258              
259 10         38 my @membernames;
260             my @argnames;
261 10         0 my @memberhandlers;
262              
263 10         25 my $argindex = 0;
264 10         20 my @members = @{ $params{members} };
  10         46  
265 10         231 foreach ( pairs @members ) {
266 20         215 my $memname = $_->key;
267 20         110 my $handler = $_->value;
268              
269 20         67 push @membernames, $memname;
270 20         42 push @memberhandlers, $handler;
271              
272 20         67 $handler->{set_names}->( $basename, $memname );
273              
274 20         45 my $wasindex = $argindex;
275 20         58 $handler->{set_arg}( $argindex );
276              
277 20 100       87 push @argnames, $memname if $argindex > $wasindex;
278             }
279              
280 10 100       84 push @fragments, "#ifdef $params{ifdef}" if $params{ifdef};
281             push @fragments,
282             " {",
283             " $name $basename;",
284             qq[ printf("$basename=%lu,", (unsigned long)sizeof($basename));],
285 10         84 ( map { " " . $_->{gen_c}->() } @memberhandlers ),
  20         52  
286             qq[ printf("\\n");],
287             " }";
288 10 100       53 push @fragments, "#endif" if $params{ifdef};
289              
290             push @genblocks, [ $basename => sub {
291 10     10   121 my ( $result ) = @_;
292 10 100       122 return () unless defined $result;
293              
294 9         169 my @result = split m/,/, $result;
295              
296 9         63 my $curpos = 0;
297              
298 9         117 my $format = "";
299              
300 9         64 my $sizeof = shift @result;
301              
302 9         47 my ( @postargs, @preret );
303              
304 9         60 foreach my $def ( @result ) {
305 19         242 my $handler = shift @memberhandlers;
306              
307 19         262 $format .= $handler->{gen_format}( $def, $curpos, \@postargs, \@preret ) . " ";
308             }
309              
310 9 100       149 if( $curpos < $sizeof ) {
311 2         31 $format .= "x" . ( $sizeof - $curpos );
312             }
313              
314 9         93 my $eq = "==";
315 9 100       87 if( $with_tail ) {
316 1         7 $format .= "a*";
317 1         22 $eq = ">=";
318             }
319              
320 9 50       202 unshift( @perlcode, "use Carp;" ), $done_carp++ unless $done_carp;
321              
322 9         38 my ( @argcode, @retcode );
323 9 100       61 if( $arg_style eq "list" ) {
    50          
324 8 100       77 my $members = join( ", ", @argnames, ( $with_tail ? "[tail]" : () ) );
325              
326 8         112 @argcode = (
327             qq{ \@_ $eq $argindex or croak "usage: $packfunc($members)";},
328             qq{ my \@v = \@_;} );
329 8         79 @retcode = (
330             qq{ \@v;} );
331             }
332             elsif( $arg_style eq "hashref" ) {
333 1 50       5 my $qmembers = join( ", ", map { "'$_'" } @membernames, ( $with_tail ? "_tail" : () ) );
  2         15  
334              
335 1         12 @argcode = (
336             qq{ ref(\$_[0]) eq "HASH" or croak "usage: $packfunc(\\%args)";},
337             qq( my \@v = \@{\$_[0]}{$qmembers};) );
338 1         9 @retcode = (
339             # Seems we can't easily do this without a temporary
340             qq( my %ret; \@ret{$qmembers} = \@v;),
341             qq{ \\%ret;} );
342             }
343             else {
344 0         0 carp "Unrecognised arg_style $arg_style";
345             }
346              
347 9         129 push_export $packfunc;
348 9         62 push_export $unpackfunc;
349              
350 9 100       334 join( "\n",
351             "",
352             "sub $packfunc",
353             "{",
354             @argcode,
355             @postargs,
356             qq{ pack "$format", \@v;},
357             "}",
358             "",
359             "sub $unpackfunc",
360             "{",
361             ( $no_length_check ? '' :
362             qq{ length \$_[0] $eq $sizeof or croak "$unpackfunc: expected $sizeof bytes, got " . length \$_[0];}
363             ),
364             qq{ my \@v = unpack "$format", \$_[0];},
365             @preret,
366             @retcode,
367             "}"
368             );
369 10         227 } ];
370             }
371              
372             =pod
373              
374             The following structure member definitions are allowed:
375              
376             =over 4
377              
378             =cut
379              
380             my %struct_formats = (
381             map {
382             my $bytes = length( pack "$_", 0 );
383             "${bytes}u" => uc $_,
384             "${bytes}s" => lc $_
385             } qw( C S L )
386             );
387              
388             if( eval { pack "Q", 0 } ) {
389             my $bytes = length( pack "Q", 0 );
390             $struct_formats{"${bytes}u"} = "Q";
391             $struct_formats{"${bytes}s"} = "q";
392             }
393              
394             =item * member_numeric
395              
396             The field contains a single signed or unsigned number. Its size and signedness
397             will be automatically detected.
398              
399             =cut
400              
401             my $done_u64;
402              
403             sub member_numeric
404             {
405 18     18 1 107 my $varname;
406             my $membername;
407 18         0 my $argindex;
408              
409             return {
410 18     18   55 set_names => sub { ( $varname, $membername ) = @_; },
411 17     17   36 set_arg => sub { $argindex = $_[0]++; },
412              
413             gen_c => sub {
414 18     18   238 qq{printf("$membername@%ld+%lu%c,", } .
415             "(long)((char*)&$varname.$membername-(char*)&$varname), " . # offset
416             "(unsigned long)sizeof($varname.$membername), " . # size
417             "($varname.$membername=-1)>0?'u':'s'" . # signedness
418             ");";
419             },
420             gen_format => sub {
421 17     17   108 my ( $def, undef, $postarg, $preret ) = @_;
422             # ( undef, curpos ) = @_;
423              
424 17 50       409 my ( $member, $offs, $size, $sign ) = $def =~ m/^([\w.]+)@(\d+)\+(\d+)([us])$/
425             or die "Could not parse member definition out of '$def'";
426              
427 17 50       161 $member eq $membername or die "Expected definition of $membername but found $member instead";
428              
429 17         122 my $format = "";
430 17 50       274 if( $offs > $_[1] ) {
    50          
431 0         0 my $pad = $offs - $_[1];
432              
433 0         0 $format .= "x" x $pad;
434 0         0 $_[1] += $pad;
435             }
436             elsif( $offs < $_[1] ) {
437 0         0 die "Err.. need to go backwards for structure $varname member $member";
438             }
439              
440 17 50 0     128 if( exists $struct_formats{"$size$sign"} ) {
    0          
441 17         100 $format .= $struct_formats{"$size$sign"};
442             }
443             elsif( $size == 8 and $sign eq "u" ) {
444             # 64bit int on a 64bit-challenged perl. We'll have to improvise
445              
446 0 0       0 unless( $done_u64 ) {
447 0         0 my $hilo = pack("S",0x0201) eq "\x02\x01" ? "\$hi, \$lo" : "\$lo, \$hi";
448              
449 0         0 perlcode join "\n",
450             "require Math::BigInt;",
451             "",
452             "sub __pack_u64 {",
453             " my ( \$hi, \$lo ) = ( int(\$_[0] / 2**32), \$_[0] & 0xffffffff );",
454             " pack( \"L L\", $hilo );",
455             "}",
456             "",
457             "sub __unpack_u64 {",
458             " length \$_[0] == 8 or return undef;", # in case of no_length_check
459             " my ( $hilo ) = unpack( \"L L\", \$_[0] );",
460             " return \$lo if \$hi == 0;",
461             " my \$n = Math::BigInt->new(\$hi); \$n <<= 32; \$n |= \$lo;",
462             " return \$n;",
463             "}",
464             "";
465              
466 0         0 $done_u64++;
467             }
468              
469 0         0 push @$postarg, " \$v[$argindex] = __pack_u64( \$v[$argindex] );";
470 0         0 push @$preret, " \$v[$argindex] = __unpack_u64( \$v[$argindex] );";
471            
472              
473 0         0 $format .= "a8";
474             }
475             else {
476 0         0 die "Cannot find a pack format for size $size sign $sign";
477             }
478              
479 17         121 $_[1] += $size;
480 17         1563 return $format;
481             },
482 18         536 };
483             }
484              
485             =item * member_strarray
486              
487             The field contains a NULL-padded string of characters. Its size will be
488             automatically detected.
489              
490             =cut
491              
492             sub member_strarray
493             {
494 2     2 1 10 my $varname;
495             my $membername;
496 2         0 my $argindex;
497              
498             return {
499 2     2   16 set_names => sub { ( $varname, $membername ) = @_; },
500 2     2   4 set_arg => sub { $argindex = $_[0]++; },
501              
502             gen_c => sub {
503 2     2   21 qq{printf("$membername@%ld+%lu,", } .
504             "(long)((char*)&$varname.$membername-(char*)&$varname), " . # offset
505             "(unsigned long)sizeof($varname.$membername)" . # size
506             ");";
507             },
508             gen_format => sub {
509 2     2   10 my ( $def ) = @_;
510              
511 2 50       49 my ( $member, $offs, $size ) = $def =~ m/^([\w.]+)@(\d+)\+(\d+)$/
512             or die "Could not parse member definition out of '$def'";
513              
514 2 50       20 $member eq $membername or die "Expected definition of $membername but found $member instead";
515              
516 2         7 my $format = "";
517 2 50       81 if( $offs > $_[1] ) {
    50          
518 0         0 my $pad = $offs - $_[1];
519              
520 0         0 $format .= "x" x $pad;
521 0         0 $_[1] += $pad;
522             }
523             elsif( $offs < $_[1] ) {
524 0         0 die "Err.. need to go backwards for structure $varname member $member";
525             }
526              
527 2         11 $format .= "Z$size";
528 2         10 $_[1] += $size;
529              
530 2         113 return $format;
531             },
532 2         66 };
533             }
534              
535             =item * member_constant($code)
536              
537             The field contains a single number as for C. Instead of
538             consuming/returning a value in the arguments list, this member will be packed
539             from an expression, or asserted that it contains the given value. The string
540             C<$code> will be inserted into the generated pack and unpack functions, so it
541             can be used for constants generated by the C directive.
542              
543             =cut
544              
545             sub member_constant
546             {
547 1     1 1 12 my $value = shift;
548              
549 1         4 my $constant = member_numeric;
550              
551 1         2 my $arg_index;
552 1     1   14 $constant->{set_arg} = sub { $arg_index = $_[0] }; # no inc
  1         2  
553              
554 1         3 my $gen_format = delete $constant->{gen_format};
555             $constant->{gen_format} = sub {
556 1     1   6 my ( $def, undef, $postarg, $preret ) = @_;
557              
558 1 50       66 my ( $member ) = $def =~ m/^([\w.]+)@/
559             or die "Could not parse member definition out of '$def'";
560              
561 1         18 push @$postarg, " splice \@v, $arg_index, 0, $value;";
562              
563 1         10 my $format = $gen_format->( @_ );
564              
565 1         11 push @$preret, " splice( \@v, $arg_index, 1 ) == $value or croak \"expected $member == $value\";";
566              
567 1         115 return $format;
568 1         4 };
569              
570 1         9 $constant;
571             }
572              
573             =back
574              
575             The structure definition results in two new functions being created,
576             C and C, where C<$name> is the name of the structure
577             (with the leading C prefix stripped). These behave similarly to the
578             familiar functions such as C; the C function will
579             take a list of fields and return a packed string, the C function will
580             take a string and return a list of fields.
581              
582             =cut
583              
584             =head2 no_export
585              
586             =head2 use_export
587              
588             =head2 use_export_ok
589              
590             no_export;
591             use_export;
592             use_export_ok;
593              
594             Controls the export behaviour of the generated symbols. C creates
595             symbols that are not exported by their package, they must be used fully-
596             qualified. C creates symbols that are exported by default.
597             C creates symbols that are exported if they are specifically
598             requested at C time.
599              
600             The mode can be changed at any time to affect only the symbols that follow
601             it. It defaults to C.
602              
603             =cut
604              
605 1     1 1 25 sub no_export { $export_mode = 0 }
606 1     1 1 28 sub use_export { $export_mode = 1 }
607 10     10 1 22 sub use_export_ok { $export_mode = "OK" }
608              
609             my $cbuilder = ExtUtils::CBuilder->new( quiet => 1 );
610             my %compile_args;
611             my %link_args;
612              
613             if( my $mb = eval { require Module::Build and Module::Build->current } ) {
614             $compile_args{include_dirs} = $mb->include_dirs;
615             $compile_args{extra_compiler_flags} = $mb->extra_compiler_flags;
616              
617             $link_args{extra_linker_flags} = $mb->extra_linker_flags;
618             }
619              
620             sub gen_perl
621             {
622 18 50   18 0 109 return "" unless @fragments;
623              
624 18         163 my $c_file = join "\n",
625             "#include ",
626             @preamble,
627             "",
628             "int main(void) {",
629             @fragments,
630             " return 0;",
631             "}\n";
632              
633 18         54 undef @preamble;
634 18         49 undef @fragments;
635              
636 18 50       72 die "Cannot generate a C file yet - no module name\n" unless defined $modulename;
637              
638 18         87 my $tempname = "gen-$modulename";
639              
640 18         90 my $sourcename = "$tempname.c";
641             {
642 18 50       42 open( my $source_fh, "> $sourcename" ) or die "Cannot write $sourcename - $!";
  18         2566  
643 18         1673 print $source_fh $c_file;
644             }
645              
646 18         87 my $objname = eval { $cbuilder->compile( source => $sourcename, %compile_args ) };
  18         575  
647              
648 18         786691 unlink $sourcename;
649              
650 18 50       560 if( !defined $objname ) {
651 0         0 die "Failed to compile source\n";
652             }
653              
654 18         148 my $exename = eval { $cbuilder->link_executable( objects => $objname, %link_args ) };
  18         1337  
655              
656 18         684635 unlink $objname;
657              
658 18 50       435 if( !defined $exename ) {
659 0         0 die "Failed to link executable\n";
660             }
661              
662 18         136 my $output;
663             {
664 18 50       144 open( my $runh, "./$exename |" ) or die "Cannot pipeopen $exename - $!";
  18         63506  
665              
666 18         928 local $/;
667 18         11716 $output = <$runh>;
668             }
669              
670 18         1737 unlink $exename;
671              
672 18         804 my %results = map { m/^(\w+)=(.*)$/ } split m/\n/, $output;
  17         1009  
673              
674 18         241 my $perl = "";
675              
676 18         138 my @bodylines;
677              
678             # Evaluate these first, so they have a chance to push_export()
679 18         351 foreach my $genblock ( @genblocks ) {
680 19         274 my ( $key, $code ) = @$genblock;
681              
682 19         506 push @bodylines, $code->( $results{$key} );
683             }
684              
685 18 50       162 if( @exports ) {
686 0         0 $perl .= "push \@EXPORT, " . join( ", ", map { "'$_'" } @exports ) . ";\n";
  0         0  
687 0         0 undef @exports;
688             }
689              
690 18 100       127 if( @exports_ok ) {
691 13         87 $perl .= "push \@EXPORT_OK, " . join( ", ", map { "'$_'" } @exports_ok ) . ";\n";
  23         224  
692 13         89 undef @exports_ok;
693             }
694              
695 18         98 $perl .= join "", map { "$_\n" } @bodylines;
  17         159  
696              
697 18         1018 undef @genblocks;
698              
699 18         158 my @thisperlcode = @perlcode;
700 18         123 undef @perlcode;
701              
702 18         593 return join "\n", @thisperlcode, $perl;
703             }
704              
705             =head2 gen_output
706              
707             $perl = gen_output;
708              
709             Returns the generated perl code. This is used internally for testing purposes
710             but normally would not be necessary; see instead C.
711              
712             =cut
713              
714             sub gen_output
715             {
716 18     18 1 117 my $ret = $output . gen_perl . "\n1;\n";
717 18         199 $output = "";
718              
719 18         478 return $ret;
720             }
721              
722             =head2 write_output
723              
724             write_output $filename;
725              
726             Write the generated perl code into the named file. This would normally be used
727             as the last function in the containing script, to generate the output file. In
728             the case of C or C invoking the script,
729             the path to the file to be generated should be given in C<$ARGV[0]>. Normally,
730             therefore, the script would end with
731              
732             write_output $ARGV[0];
733              
734             =cut
735              
736             sub write_output
737             {
738 0     0 1 0 my ( $filename ) = @_;
739              
740 0         0 my $output = gen_output();
741              
742 0 0       0 open( my $outfile, ">", $filename ) or die "Cannot write '$filename' - $!";
743              
744 0         0 print $outfile $output;
745             }
746              
747             =head2 include_path
748              
749             include_path $path
750              
751             Adds an include path to the list of paths used by the compiler
752              
753             =cut
754              
755             sub include_path
756             {
757 1     1 1 11 my ( $path ) = @_;
758              
759 1         2 push @{ $compile_args{include_dirs} }, $path;
  1         5  
760             }
761              
762             =head2 define
763              
764             define $symbol;
765             define $symbol, $value;
766              
767             Adds a symbol to be defined on the compiler's commandline, by using the C<-D>
768             option. This is sometimes required to turn on particular optional parts of the
769             included files. An optional value can also be specified.
770              
771             =cut
772              
773             sub define
774             {
775 1     1 1 15 my ( $symbol, $value ) = @_;
776              
777 1 50       4 if( defined $value ) {
778 1         1 push @{ $compile_args{extra_compiler_flags} }, "-D$symbol=$value";
  1         8  
779             }
780             else {
781 0           push @{ $compile_args{extra_compiler_flags} }, "-D$symbol";
  0            
782             }
783             }
784              
785             =head1 EXAMPLES
786              
787             Normally this module would be used by another module at build time, to
788             construct the relevant constants and structure functions from system headers.
789              
790             For example, suppose your operating system defines a new type of socket, which
791             has its own packet and address families, and perhaps some new socket options
792             which are valid on this socket. We can build a module to contain the relevant
793             constants and structure functions by writing, for example:
794              
795             #!/usr/bin/perl
796              
797             use ExtUtils::H2PM;
798              
799             module "Socket::Moonlaser";
800              
801             include "moon/laser.h";
802              
803             constant "AF_MOONLASER";
804             constant "PF_MOONLASER";
805              
806             constant "SOL_MOONLASER";
807              
808             constant "MOONLASER_POWER", name => "POWER";
809             constant "MOONLASER_WAVELENGTH", name => "WAVELENGTH";
810              
811             structure "struct laserwl",
812             members => [
813             lwl_nm_coarse => member_numeric,
814             lwl_nm_fine => member_numeric,
815             ];
816              
817             write_output $ARGV[0];
818              
819             If we save this script as, say, F, then when the
820             distribution is built, the script will be used to generate the contents of the
821             file F. Once installed, any other code can simply
822              
823             use Socket::Moonlaser qw( AF_MOONLASER );
824              
825             to import a constant.
826              
827             The method described above doesn't allow us any room to actually include other
828             code in the module. Perhaps, as well as these simple constants, we'd like to
829             include functions, documentation, etc... To allow this, name the script
830             instead something like F, so that this is
831             the name used for the generated output. The code can then be included in the
832             actual F (which will just be a normal perl module) by
833              
834             package Socket::Moonlaser;
835              
836             use Socket::Moonlaser_const;
837              
838             sub get_power
839             {
840             getsockopt( $_[0], SOL_MOONLASER, POWER );
841             }
842              
843             sub set_power
844             {
845             setsockopt( $_[0], SOL_MOONLASER, POWER, $_[1] );
846             }
847              
848             sub get_wavelength
849             {
850             my $wl = getsockopt( $_[0], SOL_MOONLASER, WAVELENGTH );
851             defined $wl or return;
852             unpack_laserwl( $wl );
853             }
854              
855             sub set_wavelength
856             {
857             my $wl = pack_laserwl( $_[1], $_[2] );
858             setsockopt( $_[0], SOL_MOONLASER, WAVELENGTH, $wl );
859             }
860              
861             1;
862              
863             Sometimes, the actual C structure layout may not exactly match the semantics
864             we wish to present to perl modules using this extension wrapper. Socket
865             address structures typically contain their address family as the first member,
866             whereas this detail isn't exposed by, for example, the C and
867             C functions. To cope with this case, the low-level structure
868             packing and unpacking functions can be generated with a different name, and
869             wrapped in higher-level functions in the main code. For example, in
870             F:
871              
872             no_export;
873              
874             structure "struct sockaddr_ml",
875             pack_func => "_pack_sockaddr_ml",
876             unpack_func => "_unpack_sockaddr_ml",
877             members => [
878             ml_family => member_numeric,
879             ml_lat_deg => member_numeric,
880             ml_long_deg => member_numeric,
881             ml_lat_fine => member_numeric,
882             ml_long_fine => member_numeric,
883             ];
884              
885             This will generate a pack/unpack function pair taking or returning five
886             arguments; these functions will not be exported. In our main F
887             file we can wrap these to actually expose a different API:
888              
889             sub pack_sockaddr_ml
890             {
891             @_ == 2 or croak "usage: pack_sockaddr_ml(lat, long)";
892             my ( $lat, $long ) = @_;
893              
894             return _pack_sockaddr_ml( AF_MOONLASER, int $lat, int $long,
895             ($lat - int $lat) * 1_000_000, ($long - int $long) * 1_000_000);
896             }
897              
898             sub unpack_sockaddr_ml
899             {
900             my ( $family, $lat, $long, $lat_fine, $long_fine ) =
901             _unpack_sockaddr_ml( $_[0] );
902              
903             $family == AF_MOONLASER or croak "expected family AF_MOONLASER";
904              
905             return ( $lat + $lat_fine/1_000_000, $long + $long_fine/1_000_000 );
906             }
907              
908             Sometimes, a structure will contain members which are themselves structures.
909             Suppose a different definition of the above address, which at the C layer is
910             defined as
911              
912             struct angle
913             {
914             short deg;
915             unsigned long fine;
916             };
917              
918             struct sockaddr_ml
919             {
920             short ml_family;
921             struct angle ml_lat, ml_long;
922             };
923              
924             We can instead "flatten" this structure tree to obtain the five fields by
925             naming the sub-members of the outer structure:
926              
927             structure "struct sockaddr_ml",
928             members => [
929             "ml_family" => member_numeric,
930             "ml_lat.deg" => member_numeric,
931             "ml_lat.fine" => member_numeric,
932             "ml_long.deg" => member_numeric,
933             "ml_long.fine" => member_numeric,
934             ];
935              
936             =head1 TODO
937              
938             =over 4
939              
940             =item *
941              
942             Consider more structure members. With strings comes the requirement to have
943             members that store a size. This requires cross-referential members. And while
944             we're at it it might be nice to have constant members; fill in constants
945             without consuming arguments when packing, assert the right value on unpacking.
946              
947             =back
948              
949             =head1 AUTHOR
950              
951             Paul Evans
952              
953             =cut
954              
955             0x55AA;