File Coverage

blib/lib/ExtUtils/H2PM.pm
Criterion Covered Total %
statement 178 211 84.3
branch 49 78 62.8
condition 8 14 57.1
subroutine 30 32 93.7
pod 12 15 80.0
total 277 350 79.1


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