#
# Tim.Bunce@ig.co.uk, August 1994
+use vars qw($VERSION);
+
+$VERSION = "1.02";
+
require Carp;
require Config;
+
require AutoLoader;
+*AUTOLOAD = \&AutoLoader::AUTOLOAD;
-@ISA=qw(AutoLoader);
+# enable debug/trace messages from DynaLoader perl code
+$dl_debug = $ENV{PERL_DL_DEBUG} || 0 unless defined $dl_debug;
+#
+# Flags to alter dl_load_file behaviour. Assigned bits:
+# 0x01 make symbols available for linking later dl_load_file's.
+# (only known to work on Solaris 2 using dlopen(RTLD_GLOBAL))
+# (ignored under VMS; effect is built-in to image linking)
+#
+# This is called as a class method $module->dl_load_flags. The
+# definition here will be inherited and result on "default" loading
+# behaviour unless a sub-class of DynaLoader defines its own version.
+#
-sub import { } # override import inherited from AutoLoader
+sub dl_load_flags { 0x00 }
-# enable debug/trace messages from DynaLoader perl code
-$dl_debug = $ENV{PERL_DL_DEBUG} || 0 unless defined $dl_debug;
+#
-($dl_dlext, $dlsrc, $osname)
- = @Config::Config{'dlext', 'dlsrc', 'osname'};
+($dl_dlext, $dlsrc)
+ = @Config::Config{'dlext', 'dlsrc'};
# Some systems need special handling to expand file specifications
# (VMS support by Charles Bailey <bailey@HMIVAX.HUMGEN.UPENN.EDU>)
# See dl_expandspec() for more details. Should be harmless but
# inefficient to define on systems that don't need it.
-$do_expand = ($osname eq 'VMS');
+$do_expand = $Is_VMS = $^O eq 'VMS';
@dl_require_symbols = (); # names of symbols we need
@dl_resolve_using = (); # names of files to link with
@dl_library_path = (); # path to look for files
+@dl_librefs = (); # things we have loaded
+@dl_modules = (); # Modules we have loaded
# This is a fix to support DLD's unfortunate desire to relink -lc
@dl_resolve_using = dl_findfile('-lc') if $dlsrc eq "dl_dld.xs";
# No prizes for guessing why we don't say 'bootstrap DynaLoader;' here.
-boot_DynaLoader() if defined(&boot_DynaLoader);
+boot_DynaLoader('DynaLoader') if defined(&boot_DynaLoader);
if ($dl_debug) {
local($module) = $args[0];
local(@dirs, $file);
- Carp::confess "Usage: DynaLoader::bootstrap(module)" unless $module;
+ Carp::confess("Usage: DynaLoader::bootstrap(module)") unless $module;
# A common error on platforms which don't support dynamic loading.
# Since it's fatal and potentially confusing we give a detailed message.
"(auto/$modpname/$modfname.$dl_dlext)\n" if $dl_debug;
foreach (@INC) {
+ chop($_ = VMS::Filespec::unixpath($_)) if $Is_VMS;
my $dir = "$_/auto/$modpname";
next unless -d $dir; # skip over uninteresting directories
# last resort, let dl_findfile have a go in all known locations
$file = dl_findfile(@dirs, map("-L$_",@INC), $modfname) unless $file;
- Carp::croak "Can't find loadable object for module $module in \@INC (@INC)"
+ Carp::croak("Can't find loadable object for module $module in \@INC (@INC)")
unless $file;
my $bootname = "boot_$module";
my $bs = $file;
$bs =~ s/(\.\w+)?$/\.bs/; # look for .bs 'beside' the library
if (-s $bs) { # only read file if it's not empty
- print STDERR "BS: $bs ($osname, $dlsrc)\n" if $dl_debug;
+ print STDERR "BS: $bs ($^O, $dlsrc)\n" if $dl_debug;
eval { do $bs; };
warn "$bs: $@\n" if $@;
}
# in this perl code simply because this was the last perl code
# it executed.
- my $libref = dl_load_file($file) or
- Carp::croak "Can't load '$file' for module $module: ".dl_error()."\n";
+ my $libref = dl_load_file($file, $module->dl_load_flags) or
+ Carp::croak("Can't load '$file' for module $module: ".dl_error()."\n");
+
+ push(@dl_librefs,$libref); # record loaded object
my @unresolved = dl_undef_symbols();
- Carp::carp "Undefined symbols present after loading $file: @unresolved\n"
+ Carp::carp("Undefined symbols present after loading $file: @unresolved\n")
if @unresolved;
my $boot_symbol_ref = dl_find_symbol($libref, $bootname) or
- Carp::croak "Can't find '$bootname' symbol in $file\n";
+ Carp::croak("Can't find '$bootname' symbol in $file\n");
my $xs = dl_install_xsub("${module}::bootstrap", $boot_symbol_ref, $file);
+ push(@dl_modules, $module); # record loaded module
+
# See comment block above
&$xs(@args);
}
my (@args) = @_;
my (@dirs, $dir); # which directories to search
my (@found); # full paths to real files we have found
- my $vms = ($osname eq 'VMS');
+ my $dl_ext= $Config::Config{'dlext'}; # suffix for perl extensions
my $dl_so = $Config::Config{'so'}; # suffix for shared libraries
print STDERR "dl_findfile(@args)\n" if $dl_debug;
# accumulate directories but process files as they appear
arg: foreach(@args) {
# Special fast case: full filepath requires no search
- if (m:/: && -f $_ && !$do_expand) {
+ if ($Is_VMS && m%[:>/\]]% && -f $_) {
+ push(@found,dl_expandspec(VMS::Filespec::vmsify($_)));
+ last arg unless wantarray;
+ next;
+ }
+ elsif (m:/: && -f $_ && !$do_expand) {
push(@found,$_);
last arg unless wantarray;
next;
# VMS: we may be using native VMS directry syntax instead of
# Unix emulation, so check this as well
- if ($vms && /[:>\]]/ && -d $_) { push(@dirs, $_); next; }
+ if ($Is_VMS && /[:>\]]/ && -d $_) { push(@dirs, $_); next; }
# Only files should get this far...
my(@names, $name); # what filenames to look for
push(@names,"lib$_.a");
} else { # Umm, a bare name. Try various alternatives:
# these should be ordered with the most likely first
+ push(@names,"$_.$dl_ext") unless m/\.$dl_ext$/o;
push(@names,"$_.$dl_so") unless m/\.$dl_so$/o;
push(@names,"lib$_.$dl_so") unless m:/:;
- push(@names,"$_.o") unless m/\.(o|$dl_so)$/o;
push(@names,"$_.a") if !m/\.a$/ and $dlsrc eq "dl_dld.xs";
push(@names, $_);
}
foreach $dir (@dirs, @dl_library_path) {
next unless -d $dir;
+ chop($dir = VMS::Filespec::unixpath($dir)) if $Is_VMS;
foreach $name (@names) {
my($file) = "$dir/$name";
print STDERR " checking in $dir for $name\n" if $dl_debug;
my $file = $spec; # default output to input
- if ($osname eq 'VMS') { # dl_expandspec should be defined in dl_vms.xs
- Carp::croak "dl_expandspec: should be defined in XS file!\n";
+ if ($Is_VMS) { # dl_expandspec should be defined in dl_vms.xs
+ Carp::croak("dl_expandspec: should be defined in XS file!\n");
} else {
return undef unless -f $file;
}
$file;
}
+sub dl_find_symbol_anywhere
+{
+ my $sym = shift;
+ my $libref;
+ foreach $libref (@dl_librefs) {
+ my $symref = dl_find_symbol($libref,$sym);
+ return $symref if $symref;
+ }
+ return undef;
+}
=head1 NAME
DynaLoader - Dynamically load C libraries into Perl code
-dl_error(), dl_findfile(), dl_expandspec(), dl_load_file(), dl_find_symbol(), dl_undef_symbols(), dl_install_xsub(), boostrap() - routines used by DynaLoader modules
+dl_error(), dl_findfile(), dl_expandspec(), dl_load_file(), dl_find_symbol(), dl_find_symbol_anywhere(), dl_undef_symbols(), dl_install_xsub(), dl_load_flags(), bootstrap() - routines used by DynaLoader modules
=head1 SYNOPSIS
@ISA = qw(... DynaLoader ...);
bootstrap YourPackage;
+ # optional method for 'global' loading
+ sub dl_load_flags { 0x01 }
+
=head1 DESCRIPTION
It must be stressed that the DynaLoader, by itself, is practically
useless for accessing non-Perl libraries because it provides almost no
Perl-to-C 'glue'. There is, for example, no mechanism for calling a C
-library function or supplying arguments. It is anticipated that any
-glue that may be developed in the future will be implemented in a
-separate dynamically loaded module.
+library function or supplying arguments. A ExtUtils::DynaLib module
+is available from CPAN sites which performs that function for some
+common system types.
DynaLoader Interface Summary
@dl_resolve_using
@dl_require_symbols
$dl_debug
+ @dl_librefs
+ @dl_modules
Implemented in:
bootstrap($modulename) Perl
@filepaths = dl_findfile(@names) Perl
+ $flags = $modulename->dl_load_flags Perl
+ $symref = dl_find_symbol_anywhere($symbol) Perl
- $libref = dl_load_file($filename) C
+ $libref = dl_load_file($filename, $flags) C
$symref = dl_find_symbol($libref, $symbol) C
@symbols = dl_undef_symbols() C
dl_install_xsub($name, $symref [, $filename]) C
later call to load_file().
This is only required on some platforms which do not handle dependent
-libraries automatically. For example the Socket Perl extension library
-(F<auto/Socket/Socket.so>) contains references to many socket functions
-which need to be resolved when it's loaded. Most platforms will
-automatically know where to find the 'dependent' library (e.g.,
-F</usr/lib/libsocket.so>). A few platforms need to to be told the location
-of the dependent library explicitly. Use @dl_resolve_using for this.
+libraries automatically. For example the Socket Perl extension
+library (F<auto/Socket/Socket.so>) contains references to many socket
+functions which need to be resolved when it's loaded. Most platforms
+will automatically know where to find the 'dependent' library (e.g.,
+F</usr/lib/libsocket.so>). A few platforms need to be told the
+location of the dependent library explicitly. Use @dl_resolve_using
+for this.
Example usage:
A list of one or more symbol names that are in the library/object file
to be dynamically loaded. This is only required on some platforms.
+=item @dl_librefs
+
+An array of the handles returned by successful calls to dl_load_file(),
+made by bootstrap, in the order in which they were loaded.
+Can be used with dl_find_symbol() to look for a symbol in any of
+the loaded files.
+
+=item @dl_modules
+
+An array of module (package) names that have been bootstrap'ed.
+
=item dl_error()
Syntax:
Syntax:
- $libref = dl_load_file($filename)
+ $libref = dl_load_file($filename, $flags)
Dynamically load $filename, which must be the path to a shared object
or library. An opaque 'library reference' is returned as a handle for
the loaded object. Returns undef on error.
+The $flags argument to alters dl_load_file behaviour.
+Assigned bits:
+
+ 0x01 make symbols available for linking later dl_load_file's.
+ (only known to work on Solaris 2 using dlopen(RTLD_GLOBAL))
+ (ignored under VMS; this is a normal part of image linking)
+
(On systems that provide a handle for the loaded object such as SunOS
and HPUX, $libref will be that handle. On other systems $libref will
typically be $filename or a pointer to a buffer containing $filename.
The application should not examine or alter $libref in any way.)
-This is function that does the real work. It should use the current
-values of @dl_require_symbols and @dl_resolve_using if required.
+This is the function that does the real work. It should use the
+current values of @dl_require_symbols and @dl_resolve_using if required.
SunOS: dlopen($filename)
HP-UX: shl_load($filename)
NeXT: rld_load($filename, @dl_resolve_using)
VMS: lib$find_image_symbol($filename,$dl_require_symbols[0])
+(The dlopen() function is also used by Solaris and some versions of
+Linux, and is a common choice when providing a "wrapper" on other
+mechanisms as is done in the OS/2 port.)
+
+=item dl_loadflags()
+
+Syntax:
+
+ $flags = dl_loadflags $modulename;
+
+Designed to be a method call, and to be overridden by a derived class
+(i.e. a class which has DynaLoader in its @ISA). The definition in
+DynaLoader itself returns 0, which produces standard behavior from
+dl_load_file().
=item dl_find_symbol()
VMS: lib$find_image_symbol($libref,$symbol)
+=item dl_find_symbol_anywhere()
+
+Syntax:
+
+ $symref = dl_find_symbol_anywhere($symbol)
+
+Applies dl_find_symbol() to the members of @dl_librefs and returns
+the first match found.
+
=item dl_undef_symbols()
Example
$filename is not defined then "DynaLoader" will be used.
-=item boostrap()
+=item bootstrap()
Syntax:
=item *
+calls dl_load_flags() to determine how to load the file.
+
+=item *
+
calls dl_load_file() to load the file
=item *
Larry Wall designed the elegant inherited bootstrap mechanism and
implemented the first Perl 5 dynamic loader using it.
+Solaris global loading added by Nick Ing-Simmons with design/coding
+assistance from Tim Bunce, January 1996.
+
=cut