package XSLoader;
-# And Gandalf said: 'Many folk like to know beforehand what is to
-# be set on the table; but those who have laboured to prepare the
-# feast like to keep their secret; for wonder makes the words of
-# praise louder.'
-
-# (Quote from Tolkien sugested by Anno Siegel.)
-#
-# See pod text at end of file for documentation.
-# See also ext/DynaLoader/README in source tree for other information.
-#
-# Tim.Bunce@ig.co.uk, August 1994
-
-$VERSION = "0.01"; # avoid typo warning
+$VERSION = "0.03";
# enable debug/trace messages from DynaLoader perl code
# $dl_debug = $ENV{PERL_DL_DEBUG} || 0 unless defined $dl_debug;
!defined(&dl_error);
package XSLoader;
-1; # End of main code
-
-# The bootstrap function cannot be autoloaded (without complications)
-# so we define it here:
-
sub load {
package DynaLoader;
+ die q{XSLoader::load('Your::Module', $Your::Module::VERSION)} unless @_;
+
my($module) = $_[0];
# work with static linking too
$bootname =~ s/\W/_/g;
@dl_require_symbols = ($bootname);
+ my $boot_symbol_ref;
+
+ if ($^O eq 'darwin') {
+ if ($boot_symbol_ref = dl_find_symbol(0, $bootname)) {
+ goto boot; #extension library has already been loaded, e.g. darwin
+ }
+ }
+
# Many dynamic extension loading problems will appear to come from
# this section of code: XYZ failed at line 123 of DynaLoader.pm.
# Often these errors are actually occurring in the initialisation
Carp::carp("Undefined symbols present after loading $file: @unresolved\n");
}
- my $boot_symbol_ref = dl_find_symbol($libref, $bootname) or do {
+ $boot_symbol_ref = dl_find_symbol($libref, $bootname) or do {
require Carp;
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
+ boot:
+ my $xs = dl_install_xsub("${module}::bootstrap", $boot_symbol_ref, $file);
+
# See comment block above
+ push(@DynaLoader::dl_shared_objects, $file); # record files loaded
return &$xs(@_);
retry:
goto &DynaLoader::bootstrap_inherit;
}
+1;
+
__END__
=head1 NAME
package YourPackage;
use XSLoader;
- XSLoader::load 'YourPackage', @args;
+ XSLoader::load 'YourPackage', $YourPackage::VERSION;
=head1 DESCRIPTION
linking mechanisms available on many platforms. Its primary purpose is
to implement cheap automatic dynamic loading of Perl modules.
-For more complicated interface see L<DynaLoader>.
+For a more complicated interface, see L<DynaLoader>. Many (most)
+features of DynaLoader are not implemented in XSLoader, like for
+example the dl_load_flags, not honored by XSLoader.
+
+=head2 Migration from C<DynaLoader>
+
+A typical module using L<DynaLoader|DynaLoader> starts like this:
+
+ package YourPackage;
+ require DynaLoader;
+
+ our @ISA = qw( OnePackage OtherPackage DynaLoader );
+ our $VERSION = '0.01';
+ bootstrap YourPackage $VERSION;
+
+Change this to
+
+ package YourPackage;
+ use XSLoader;
+
+ our @ISA = qw( OnePackage OtherPackage );
+ our $VERSION = '0.01';
+ XSLoader::load 'YourPackage', $VERSION;
+
+In other words: replace C<require DynaLoader> by C<use XSLoader>, remove
+C<DynaLoader> from @ISA, change C<bootstrap> by C<XSLoader::load>. Do not
+forget to quote the name of your package on the C<XSLoader::load> line,
+and add comma (C<,>) before the arguments ($VERSION above).
+
+Of course, if @ISA contained only C<DynaLoader>, there is no need to have the
+@ISA assignment at all; moreover, if instead of C<our> one uses the more
+backward-compatible
+
+ use vars qw($VERSION @ISA);
+
+one can remove this reference to @ISA together with the @ISA assignment.
+
+If no $VERSION was specified on the C<bootstrap> line, the last line becomes
+
+ XSLoader::load 'YourPackage';
+
+=head2 Backward compatible boilerplate
+
+If you want to have your cake and eat it too, you need a more complicated
+boilerplate.
+
+ package YourPackage;
+ use vars qw($VERSION @ISA);
+
+ @ISA = qw( OnePackage OtherPackage );
+ $VERSION = '0.01';
+ eval {
+ require XSLoader;
+ XSLoader::load('YourPackage', $VERSION);
+ 1;
+ } or do {
+ require DynaLoader;
+ push @ISA, 'DynaLoader';
+ bootstrap YourPackage $VERSION;
+ };
+
+The parentheses about XSLoader::load() arguments are needed since we replaced
+C<use XSLoader> by C<require>, so the compiler does not know that a function
+XSLoader::load() is present.
+
+This boilerplate uses the low-overhead C<XSLoader> if present; if used with
+an antic Perl which has no C<XSLoader>, it falls back to using C<DynaLoader>.
+
+=head1 Order of initialization: early load()
+
+I<Skip this section if the XSUB functions are supposed to be called from other
+modules only; read it only if you call your XSUBs from the code in your module,
+or have a C<BOOT:> section in your XS file (see L<perlxs/"The BOOT: Keyword">).
+What is described here is equally applicable to the L<DynaLoader|DynaLoader>
+interface.>
+
+A sufficiently complicated module using XS would have both Perl code (defined
+in F<YourPackage.pm>) and XS code (defined in F<YourPackage.xs>). If this
+Perl code makes calls into this XS code, and/or this XS code makes calls to
+the Perl code, one should be careful with the order of initialization.
+
+The call to XSLoader::load() (or bootstrap()) has three side effects:
+
+=over
+
+=item *
+
+if $VERSION was specified, a sanity check is done to ensure that the versions
+of the F<.pm> and the (compiled) F<.xs> parts are compatible;
+
+=item *
+
+the XSUBs are made accessible from Perl;
+
+=item *
+
+if a C<BOOT:> section was present in the F<.xs> file, the code there is called.
+
+=back
+
+Consequently, if the code in the F<.pm> file makes calls to these XSUBs, it is
+convenient to have XSUBs installed before the Perl code is defined; for
+example, this makes prototypes for XSUBs visible to this Perl code.
+Alternatively, if the C<BOOT:> section makes calls to Perl functions (or
+uses Perl variables) defined in the F<.pm> file, they must be defined prior to
+the call to XSLoader::load() (or bootstrap()).
+
+The first situation being much more frequent, it makes sense to rewrite the
+boilerplate as
+
+ package YourPackage;
+ use XSLoader;
+ use vars qw($VERSION @ISA);
+
+ BEGIN {
+ @ISA = qw( OnePackage OtherPackage );
+ $VERSION = '0.01';
+
+ # Put Perl code used in the BOOT: section here
+
+ XSLoader::load 'YourPackage', $VERSION;
+ }
+
+ # Put Perl code making calls into XSUBs here
+
+=head2 The most hairy case
+
+If the interdependence of your C<BOOT:> section and Perl code is
+more complicated than this (e.g., the C<BOOT:> section makes calls to Perl
+functions which make calls to XSUBs with prototypes), get rid of the C<BOOT:>
+section altogether. Replace it with a function onBOOT(), and call it like
+this:
+
+ package YourPackage;
+ use XSLoader;
+ use vars qw($VERSION @ISA);
+
+ BEGIN {
+ @ISA = qw( OnePackage OtherPackage );
+ $VERSION = '0.01';
+ XSLoader::load 'YourPackage', $VERSION;
+ }
+
+ # Put Perl code used in onBOOT() function here; calls to XSUBs are
+ # prototype-checked.
+
+ onBOOT;
+
+ # Put Perl initialization code assuming that XS is initialized here
+
+=head1 LIMITATIONS
+
+To reduce the overhead as much as possible, only one possible location
+is checked to find the extension DLL (this location is where C<make install>
+would put the DLL). If not found, the search for the DLL is transparently
+delegated to C<DynaLoader>, which looks for the DLL along the @INC list.
+
+In particular, this is applicable to the structure of @INC used for testing
+not-yet-installed extensions. This means that running uninstalled extensions
+may have much more overhead than running the same extensions after
+C<make install>.
=head1 AUTHOR