File Coverage

blib/lib/DynaLoader/Functions.pm
Criterion Covered Total %
statement 58 108 53.7
branch 24 70 34.2
condition 8 21 38.1
subroutine 11 17 64.7
pod 6 6 100.0
total 107 222 48.2


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             DynaLoader::Functions - deconstructed dynamic C library loading
4              
5             =head1 SYNOPSIS
6              
7             use DynaLoader::Functions qw(
8             loadable_for_module
9             linkable_for_loadable linkable_for_module
10             );
11              
12             $loadable = loadable_for_module("Acme::Widget");
13             @linkable = linkable_for_loadable($loadable);
14             @linkable = linkable_for_module("Acme::Widget");
15              
16             use DynaLoader::Functions
17             qw(dyna_load dyna_resolve dyna_unload);
18              
19             $libh = dyna_load($loadable, {
20             require_symbols => ["boot_Acme__Widget"],
21             });
22             my $bootfunc = dyna_resolve($libh, "boot_Acme__Widget");
23             dyna_unload($libh);
24              
25             =head1 DESCRIPTION
26              
27             This module provides a function-based interface to dynamic loading as used
28             by Perl. Some details of dynamic loading are very platform-dependent,
29             so correct use of these functions requires the programmer to be mindful
30             of the space of platform variations.
31              
32             =cut
33              
34             package DynaLoader::Functions;
35              
36 1     1   380198 { use 5.006; }
  1         4  
  1         42  
37 1     1   6 use warnings;
  1         1  
  1         25  
38 1     1   4 use strict;
  1         6  
  1         56  
39              
40             our $VERSION = "0.002";
41              
42 1     1   4 use parent "Exporter";
  1         2  
  1         17  
43             our @EXPORT_OK = qw(
44             loadable_for_module linkable_for_loadable linkable_for_module
45             dyna_load dyna_resolve dyna_unload
46             );
47              
48 1     1   117 use constant _IS_VMS => $^O eq "VMS";
  1         1  
  1         113  
49 1     1   4 use constant _IS_NETWARE => $^O eq "NetWare";
  1         1  
  1         1804  
50              
51             # It is presumed that VMS::Filespec will always be installed on VMS.
52             # It is not listed as a dependency of this module, because it is
53             # unavailable on other platforms.
54             require VMS::Filespec if _IS_VMS;
55              
56             # Load Carp lazily, as do DynaLoader and other things at this level.
57 0     0   0 sub _carp { require Carp; Carp::carp(@_); }
  0         0  
58 0     0   0 sub _croak { require Carp; Carp::croak(@_); }
  0         0  
59              
60             # Logic duplicated from Params::Classify. This is too much of an
61             # infrastructure module, an early build dependency, for it to have such
62             # a dependency.
63             sub _is_string($) {
64 6     6   15 my($arg) = @_;
65 6   33     119 return defined($arg) && ref(\$arg) eq "SCALAR";
66             }
67 1 50   1   14 sub _check_string($) { die "argument is not a string\n" unless &_is_string; }
68              
69             # Logic duplicated from Module::Runtime for the same reason.
70             sub _check_module_name($) {
71 0 0   0   0 if(!&_is_string) {
    0          
72 0         0 die "argument is not a module name\n";
73             } elsif($_[0] !~ /\A[A-Z_a-z][0-9A-Z_a-z]*(?:::[0-9A-Z_a-z]+)*\z/) {
74 0         0 die "`$_[0]' is not a module name\n";
75             }
76             }
77              
78             =head1 FUNCTIONS
79              
80             =head2 File finding
81              
82             =over
83              
84             =item loadable_for_module(MODULE_NAME)
85              
86             I<MODULE_NAME> must be the name of a Perl module, in bareword syntax with
87             C<::> separators. The named module is presumed to be an XS extension
88             following standard conventions, and its runtime-loadable C library file is
89             searched for. If found, the name of the library file is returned. If it
90             cannot be found, the function C<die>s with an informative error message.
91              
92             If the named module is actually not an XS extension, or is not installed,
93             or stores its C library in a non-standard place, there is a non-trivial
94             danger that this function will find some other library file and believe
95             it to be the right one. This function should therefore only be used
96             when there is an expectation that the module is installed and would in
97             normal operation load its corresponding C library.
98              
99             =cut
100              
101             sub loadable_for_module($) {
102 0     0 1 0 my($modname) = @_;
103 0         0 _check_module_name($modname);
104 0         0 require DynaLoader;
105             # This logic is derived from DynaLoader::bootstrap(). In places
106             # it mixes native directory names from @INC and Unix-style
107             # /-separated path syntax. This apparently works correctly
108             # everywhere, except for VMS where there's an explicit conversion.
109 0         0 my @modparts = split(/::/,$modname);
110 0         0 my $modfname = $modparts[-1];
111 0 0       0 $modfname = &DynaLoader::mod2fname(\@modparts)
112             if defined &DynaLoader::mod2fname;
113 0         0 if(_IS_NETWARE) {
114             # This ought to be part of mod2fname.
115             $modfname = substr($modfname, 0, 8);
116             }
117 0         0 my $modpname = join("/",@modparts);
118 0         0 my $loadlib = DynaLoader::dl_findfile(
119             (map {
120 0 0       0 my $d = $_;
121 0         0 if(_IS_VMS) {
122             $d = VMS::Filespec::unixpath($d);
123             chop $d;
124             }
125 0         0 "-L$d/auto/$modpname";
126             } @INC),
127             @INC,
128             $modfname)
129             or _croak "Can't locate loadable object ".
130             "for module $modname in \@INC (\@INC contains: @INC)";
131 0         0 if(_IS_VMS && $Config::Config{d_vms_case_sensitive_symbols}) {
132             $loadlib = uc($loadlib);
133             }
134 0         0 return $loadlib;
135             }
136              
137             =item linkable_for_loadable(LOADABLE_FILENAME)
138              
139             If symbols in one runtime-loadable C library are to be made available
140             to another runtime-loadable C library, depending on the platform it
141             may be necessary to refer to the exporting library when linking the
142             importing library. Generally this is not required on Unix, but it is
143             required on Windows. Where it is required to refer to the exporting
144             library at link time, the file used may be the loadable library file
145             itself, or may be a separate file used only for this purpose. Given the
146             loadable form of an exporting library, this function determines what is
147             required at link time for an importing library.
148              
149             I<LOADABLE_FILENAME> must be the name of a runtime-loadable C library
150             file. The function checks what is required to link a library that will
151             at runtime import symbols from this library. It returns a list (which
152             will be empty on many platforms) of names of files that must be used as
153             additional objects when linking the importing library.
154              
155             =cut
156              
157             my $linkable_finder = {
158             MSWin32 => sub {
159             if((my $basename = $_[0]) =~ s/\.[Dd][Ll][Ll]\z//) {
160             foreach my $suffix (qw(.lib .a)) {
161             my $impname = $basename.$suffix;
162             return ($impname) if -e $impname;
163             }
164             }
165             _croak "Can't locate linkable object for $_[0]";
166             },
167             cygwin => sub { ($_[0]) },
168             }->{$^O};
169              
170             sub linkable_for_loadable($) {
171 0     0 1 0 _check_string($_[0]);
172 0 0       0 if($linkable_finder) {
173 0         0 return $linkable_finder->($_[0]);
174             } else {
175 0         0 return ();
176             }
177             }
178              
179             =item linkable_for_module(MODULE_NAME)
180              
181             Performs the job of L</linkable_for_loadable> (which see for explanation),
182             but based on a module name instead of a loadable library filename.
183              
184             I<MODULE_NAME> must be the name of a Perl module, in bareword syntax
185             with C<::> separators. The function checks what is required to link a
186             library that will at runtime import symbols from the loadable C library
187             associated with the module. It returns a list (which will be empty
188             on many platforms) of names of files that must be used as additional
189             objects when linking the importing library.
190              
191             =cut
192              
193             sub linkable_for_module($) {
194 0 0   0 1 0 if($linkable_finder) {
195 0         0 return $linkable_finder->(loadable_for_module($_[0]));
196             } else {
197 0         0 _check_module_name($_[0]);
198 0         0 return ();
199             }
200             }
201              
202             =back
203              
204             =head2 Low-level dynamic loading
205              
206             =over
207              
208             =item dyna_load(LOADABLE_FILENAME[, OPTIONS])
209              
210             Dynamically load the runtime-loadable C library in the file named
211             I<LOADABLE_FILENAME>. The process is influenced by optional information
212             supplied in the hash referenced by I<OPTIONS>. On the platforms that
213             make dynamic loading easiest it is not necessary to supply any options
214             (in which case the parameter may be omitted), but if wide portability
215             is required then some options are required. The permitted keys in the
216             I<OPTIONS> hash are:
217              
218             =over
219              
220             =item B<resolve_using>
221              
222             Reference to an array, default empty, of names of additional library
223             files required to supply symbols used by the library being loaded.
224             On most platforms this is not used. On those platforms where it is
225             required, the need for this will be known by whatever generated the
226             library to be loaded, and it will normally be set by a bootstrap file
227             (see B<use_bootstrap_options> below).
228              
229             =item B<require_symbols>
230              
231             Reference to an array, default empty, of names of symbols expected to be
232             found in the library being loaded. On most platforms this is not used,
233             but on some a library cannot be loaded without naming at least one symbol
234             for which a need can be satisfied by the library.
235              
236             =item B<use_bootstrap_options>
237              
238             Truth value, default false, controlling whether a "bootstrap" file will
239             be consulted as an additional source of options to control loading.
240             The "bootstrap" file, if it exists, is located in the same directory as
241             the loadable library file, and has a similar name differing only in its
242             C<.bs> ending.
243              
244             =item B<symbols_global>
245              
246             Truth value, default false, indicating whether symbols found in the
247             library being loaded must be made available to subsequently-loaded
248             libraries. Depending on platform, symbols may be so available even if
249             it is not requested. Some platforms, on the other hand, can't provide
250             this facility.
251              
252             On platforms incapable of making loaded symbols globally available,
253             currently loading is liable to claim success while leaving the symbols
254             de facto unavailable. It is intended that in the future such platforms
255             will instead generate an exception when this facility is requested.
256              
257             =item B<unresolved_action>
258              
259             String keyword indicating what should be done if unresolved symbols are
260             detected while loading the library. It may be "B<ERROR>" (default)
261             to treat it as an error, "B<WARN>" to emit a warning, or "B<IGNORE>"
262             to ignore the situation. Some platforms can't detect this problem,
263             so passing this check doesn't guarantee that there won't be any runtime
264             problems due to unresolved symbols.
265              
266             =back
267              
268             On success, returns a handle that can be used to refer to the loaded
269             library for subsequent calls to L</dyna_resolve> and L</dyna_unload>.
270             On failure, C<die>s.
271              
272             =cut
273              
274             sub dyna_load($;$) {
275 1     1 1 462377 my($loadable_filename, $options) = @_;
276 1 50       19 $options = {} if @_ < 2;
277 1         18 _check_string($loadable_filename);
278 1         9 foreach(sort keys %$options) {
279 1 50       33 _croak "bad dyna_load option `$_'" unless /\A(?:
280             resolve_using|require_symbols|use_bootstrap_options|
281             symbols_global|unresolved_action
282             )\z/x;
283             }
284 1 50       11 my $unres_action = exists($options->{unresolved_action}) ?
285             $options->{unresolved_action} : "ERROR";
286 1 50 33     8 _croak "bad dyna_load unresolved_action value `$unres_action'"
287             unless _is_string($unres_action) &&
288             $unres_action =~ /\A(?:ERROR|WARN|IGNORE)\z/;
289 1         24 require DynaLoader;
290 1 50       14 _croak "dynamic loading not available in this perl"
291             unless defined &DynaLoader::dl_load_file;
292 0         0 local @DynaLoader::dl_resolve_using =
293             exists($options->{resolve_using}) ?
294 1 50       15 @{$options->{resolve_using}} : ();
295 1         11 local @DynaLoader::dl_require_symbols =
296             exists($options->{require_symbols}) ?
297 1 50       6 @{$options->{require_symbols}} : ();
298 1 50       14 if($options->{use_bootstrap_options}) {
299 0         0 (my $bs = $loadable_filename) =~
300             s/(?:\.[0-9A-Z_a-z]+)?(?:;[0-9]*)?\z/\.bs/;
301 0 0       0 if(-s $bs) {
302 0         0 eval { package DynaLoader; do $bs; };
  0         0  
303 0 0       0 warn "$bs: $@" if $@ ne "";
304             }
305             }
306 1 50       177 my $libh = DynaLoader::dl_load_file($loadable_filename,
    50          
307             $options->{symbols_global} ? 0x01 : 0)
308             or _croak "failed to load library $loadable_filename: ".
309 0         0 "@{[DynaLoader::dl_error()]}";
310 1 50 33     24 if($unres_action ne "IGNORE" &&
311             (my @unresolved = DynaLoader::dl_undef_symbols())) {
312 0         0 my $e = "undefined symbols in $loadable_filename: @unresolved";
313 0 0       0 if($unres_action eq "ERROR") {
314 0         0 DynaLoader::dl_unload_file($libh);
315 0         0 _croak $e;
316             } else {
317 0         0 _carp $e;
318             }
319             }
320 1         7 return $libh;
321             }
322              
323             =item dyna_resolve(LIBRARY_HANDLE, SYMBOL_NAME[, OPTIONS])
324              
325             Resolve the symbol I<SYMBOL> in the previously-loaded library
326             identified by the I<LIBRARY_HANDLE>. The process is influenced by
327             optional information supplied in the hash referenced by I<OPTIONS>.
328             The permitted keys in the I<OPTIONS> hash are:
329              
330             =over
331              
332             =item B<unresolved_action>
333              
334             String keyword indicating what should be done if the symbol cannot
335             be resolved. It may be "B<ERROR>" (default) to treat it as an error,
336             "B<WARN>" to emit a warning and return C<undef>, or "B<IGNORE>" to return
337             C<undef> without a warning.
338              
339             =back
340              
341             On success, returns the value of the specified symbol, in a
342             platform-dependent format. Returns C<undef> if the symbol could not be
343             resolved and this is not being treated as an error.
344              
345             =cut
346              
347             sub dyna_resolve($$;$) {
348 3     3 1 689 my($libh, $symbol, $options) = @_;
349 3 50       12 $options = {} if @_ < 3;
350 3         12 foreach(sort keys %$options) {
351 3 50       18 _croak "bad dyna_resolve option `$_'"
352             unless /\Aunresolved_action\z/;
353             }
354 3 50       13 my $unres_action = exists($options->{unresolved_action}) ?
355             $options->{unresolved_action} : "ERROR";
356 3 50 33     6 _croak "bad dyna_load unresolved_action value `$unres_action'"
357             unless _is_string($unres_action) &&
358             $unres_action =~ /\A(?:ERROR|WARN|IGNORE)\z/;
359 3         16 require DynaLoader;
360 3         120 my $val = DynaLoader::dl_find_symbol($libh, $symbol);
361 3 50 66     20 if(!defined($val) && $unres_action ne "IGNORE") {
362 0         0 my $e = "undefined symbol: $symbol";
363 0 0       0 if($unres_action eq "ERROR") {
364 0         0 _croak $e;
365             } else {
366 0         0 _carp $e;
367             }
368             }
369 3         16 return $val;
370             }
371              
372             =item dyna_unload(LIBRARY_HANDLE[, OPTIONS])
373              
374             Unload the previously-loaded library identified by the I<LIBRARY_HANDLE>.
375             The process is influenced by optional information supplied in the hash
376             referenced by I<OPTIONS>. The permitted keys in the I<OPTIONS> hash are:
377              
378             =over
379              
380             =item B<fail_action>
381              
382             String keyword indicating what should be done if unloading detectably
383             fails. It may be "B<ERROR>" (default) to treat it as an error, "B<WARN>"
384             to emit a warning, or "B<IGNORE>" to ignore the situation.
385              
386             =back
387              
388             On some platforms unloading is not possible. On any platform,
389             unloading can be expected to cause mayhem if any code from the library
390             is currently executing, if there are any live references to data in the
391             library, or if any symbols provided by the library are referenced by
392             any subsequently-loaded library.
393              
394             =cut
395              
396             sub dyna_unload($;$) {
397 1     1 1 4 my($libh, $options) = @_;
398 1 50       5 $options = {} if @_ < 2;
399 1         4 foreach(sort keys %$options) {
400 1 50       8 _croak "bad dyna_unload option `$_'" unless /\Afail_action\z/;
401             }
402 1 50       6 my $fail_action = exists($options->{fail_action}) ?
403             $options->{fail_action} : "ERROR";
404 1 50 33     4 _croak "bad dyna_load fail_action value `$fail_action'"
405             unless _is_string($fail_action) &&
406             $fail_action =~ /\A(?:ERROR|WARN|IGNORE)\z/;
407 1         3 my $err;
408 1         7 require DynaLoader;
409 1 50       7 if(defined &DynaLoader::dl_unload_file) {
410 1 50       76 DynaLoader::dl_unload_file($_[0])
411             or $err = DynaLoader::dl_error();
412             } else {
413 0         0 $err = "can't unload on this platform";
414             }
415 1 50 33     11 if(defined($err) && $fail_action ne "IGNORE") {
416 0           my $e = "failed to unload library: $err";
417 0 0         if($fail_action eq "ERROR") {
418 0           _croak $e;
419             } else {
420 0           _carp $e;
421             }
422             }
423             }
424              
425             =back
426              
427             =head1 SEE ALSO
428              
429             L<DynaLoader>,
430             L<ExtUtils::CBuilder>,
431             L<XSLoader>
432              
433             =head1 AUTHOR
434              
435             Andrew Main (Zefram) <zefram@fysh.org>
436              
437             =head1 COPYRIGHT
438              
439             Copyright (C) 2011, 2012, 2013 Andrew Main (Zefram) <zefram@fysh.org>
440              
441             =head1 LICENSE
442              
443             This module is free software; you can redistribute it and/or modify it
444             under the same terms as Perl itself.
445              
446             =cut
447              
448             1;