X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=ext%2FDynaLoader%2FXSLoader_pm.PL;h=231a28541675cb9fa0aa346296ccc39e5a0c3930;hb=8ca60cef700efb73a84648ac3b19fd3a3eecd992;hp=8cdfd634255ecc7a477401e55a553a4d3b7cd837;hpb=1d7c184104c076988718a01b77c8706aae05b092;p=p5sagit%2Fp5-mst-13.2.git diff --git a/ext/DynaLoader/XSLoader_pm.PL b/ext/DynaLoader/XSLoader_pm.PL index 8cdfd63..231a285 100644 --- a/ext/DynaLoader/XSLoader_pm.PL +++ b/ext/DynaLoader/XSLoader_pm.PL @@ -14,19 +14,7 @@ print OUT <<'EOT'; 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; @@ -37,20 +25,19 @@ print OUT ' my $dl_dlext = ', to_string($Config::Config{'dlext'}), ";\n" ; print OUT <<'EOT'; -# No prizes for guessing why we don't say 'bootstrap DynaLoader;' here. package DynaLoader; + +# No prizes for guessing why we don't say 'bootstrap DynaLoader;' here. +# NOTE: All dl_*.xs (including dl_none.xs) define a dl_error() XSUB boot_DynaLoader('DynaLoader') if defined(&boot_DynaLoader) && - !defined(&dl_load_file); + !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 @@ -90,6 +77,14 @@ print OUT <<'EOT'; $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 @@ -109,16 +104,18 @@ print OUT <<'EOT'; 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: @@ -126,6 +123,8 @@ print OUT <<'EOT'; goto &DynaLoader::bootstrap_inherit; } +1; + __END__ =head1 NAME @@ -137,7 +136,7 @@ XSLoader - Dynamically load C libraries into Perl code package YourPackage; use XSLoader; - XSLoader::load 'YourPackage', @args; + XSLoader::load 'YourPackage', $YourPackage::VERSION; =head1 DESCRIPTION @@ -145,7 +144,167 @@ This module defines a standard I interface to the dynamic 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. +For a more complicated interface, see L. 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 + +A typical module using L 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 by C, remove +C from @ISA, change C by C. Do not +forget to quote the name of your package on the C line, +and add comma (C<,>) before the arguments ($VERSION above). + +Of course, if @ISA contained only C, there is no need to have the +@ISA assignment at all; moreover, if instead of C 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 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 by C, so the compiler does not know that a function +XSLoader::load() is present. + +This boilerplate uses the low-overhead C if present; if used with +an antic Perl which has no C, it falls back to using C. + +=head1 Order of initialization: early load() + +I section in your XS file (see L). +What is described here is equally applicable to the L +interface.> + +A sufficiently complicated module using XS would have both Perl code (defined +in F) and XS code (defined in F). 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 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 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 section and Perl code is +more complicated than this (e.g., the C section makes calls to Perl +functions which make calls to XSUBs with prototypes), get rid of the C +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 +would put the DLL). If not found, the search for the DLL is transparently +delegated to C, 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. =head1 AUTHOR