Wx::Loader(3pm)
π Wx::Loader(3pm) π
Wx::Loader β and yes, it's in the User Contributed Perl Documentation family, section 3pm, obviously. Bestie, this page is the backstage pass for making Wx load its dlls your way, and if you're shipping binaries or packaging apps it's literally the whole plot. Let's get into it. π
π NAME π
Wx::Loader β using custom dll loaders with Wx.
β¨ SYNOPSIS β¨
okay so there's basically two life paths here: you're a packager, or you're shipping binary distributions. The vibes are different but the energy is the same.
#---------------------------------------
# For Packagers
#---------------------------------------
# the order of these use()s is important
use MyCustomWxLoader;
use Wx;
or .....
use threads;
use threads::shared;
use MyCustomLoader;
use Wx;
or - Wx::Perl::Splashfast special case
use MyCustomWxLoader;
use Wx::Perl::SplashFast ("./logo.jpg",5000);
use Wx;
............. meanwhile in MyCustomWxLoader.pm
package MyCustomWxLoader;
require Wx::Mini;
our @ISA = qw( Wx::Loader::Standard );
$Wx::wx_binary_loader = __PACKAGE__;
...... or
$Wx::wx_binary_loader = __PACKAGE__->new;
#-----------------------------------------
# For binary distributions
#-----------------------------------------
# Provide a custom Wx::Loader::Custom
# to be loaded by Wx::Mini
package Wx::Loader::Custom
our @ISA = qw( Wx::Loader::Standard );
# be polite if another loader is already in place
$Wx::wx_binary_loader = __PACKAGE__ if !$Wx::wx_binary_loader;
...... or
$Wx::wx_binary_loader = __PACKAGE__->new() if !$Wx::wx_binary_loader;
vibe check π¨: the order of thoseuse()s is important. Not "kinda important". Important important. The first one has to be the loader, thenWx. Do not freestyle this, bestie, the order is the whole meal. π
Also lowkey iconic that you can hand it a bare package name or a constructed object (__PACKAGE__->new). Pick your fighter. π
πΈ DESCRIPTION πΈ
So here's the situation. If you're out here providing binary distributions of Wx, or packaging Wx applications so they can run on machines that don't even have Perl installed (think PAR, PerlApp), you may need to override the dll loading methods. And the way you do that is by providing a custom wx_binary_loader package. That's it. That's the move. β¨
π¦ Binary Distributions π¦
A binary distribution can hook you up with alternative sources and loading methods for the wxWidgets dlls, and it does that by shipping a Wx::Loader::Custom module inside the distribution. Like this:
package Wx::Loader::Custom
our @ISA = qw( Wx::Loader::Standard );
# be polite if another loader is already in place
$Wx::wx_binary_loader = __PACKAGE__ if !$Wx::wx_binary_loader;
...... or
$Wx::wx_binary_loader = __PACKAGE__->new() if !$Wx::wx_binary_loader;
# remember that Wx.pm has not necessarily been loaded so only
# Wx::Mini is available
See that "be polite" comment? That's not decoration, that's etiquette. Only claim the wx_binary_loader slot if nobody's already holding it. π«Ά
And the big reminder, no cap: Wx.pm has not necessarily been loaded, so all you've got is Wx::Mini. Plan accordingly. π
π§ Perl Application Packagers π§
Applications that package perl scripts to run on machines without Perl (PAR, PerlApp etc.) can override dll loading methods if necessary, by loading a custom package before wx. Yes, before.
package MyCustomWxLoader;
require Wx::Mini;
our @ISA = qw( Wx::Loader::Standard );
$Wx::wx_binary_loader = __PACKAGE__;
...... or
$Wx::wx_binary_loader = __PACKAGE__->new;
# remember that Wx.pm has not necessarily been loaded so only
# Wx::Mini is available
Same deal, same warning, same energy: Wx.pm might not be loaded yet, so Wx::Mini is your only friend at this point in the timeline. β
π METHODS π
The following methods may be provided by custom loaders to override the default behaviour. Not all of them, not always β but they're the options on the menu, babe. π½οΈ
π loader_info
This one should return an information string about the loader, and it MUST be provided. Not optional. The default loader has:
sub loader_info { 'Standard Distribution'; }
so any custom loader should return something different from that.
e.g.
sub loader_info { "Mark's Broken Distribution - it's all my fault"; }
That example? It's giving honesty. It's giving accountability. We love to see it. π
π set_binary_path
Allows setting a custom path for the wxWidgets libraries.
sub set_binary_path {
my $class_or_object = shift;
... work out binary path
return $newbinarypath; # method MUST return a path
}
heads up π: the method MUST return a path. Not undef. Not a vibe. A path. π£οΈ
π load_dll
Is called to load wxWidgets plugin dlls using a key for the $Wx::dlls hash (see Wx::Mini).
sub load_dll {
my ($class_or_object, $dllkey) = @_;
..... load dll - or maybe not
}
The default loader does nothing β dependencies are loaded automatically and determined by the standard methods of the os. So it's not slacking, it's just that the OS has it covered, bestie.
An example of pre loading a known dependency:
sub load_dll {
return if $^O !~ /^(mswin|linux)/i;
local $ENV{PATH} = $Wx::wx_path . ';' . $ENV{PATH} if $Wx::wx_path;
return unless exists $Wx::dlls->{$_[1]} && $Wx::dlls->{$_[1]};
my $dll = $Wx::dlls->{$_[1]};
$dll = $Wx::wx_path . '/' . $dll if $Wx::wx_path;
Wx::_load_plugin( $dll );
}
π unload_dll
Is called ONCE from within an END block. A custom loader may choose, for example, to unload any dlls it has loaded.
sub unload_dll {
my $class_or_object = shift;
... carry out END actions
}
The default unload_dll is a noop:
sub unload_dll {}
Literally does nothing and is at peace with it. Iconic, honestly. π§
π external_set_load
A deprecated method of replacing the load function for plugins. A custom loader may override this to prevent a legacy loader replacing the loading methods.
π external_set_unload
A deprecated method of replacing the unload function for plugins. A custom loader may override this to prevent a legacy loader replacing the unloading methods.
deprecated alert π¨: both of these are legacy behaviour. You can override them to stop an old-school loader from stomping on your loading/unloading methods, but that's a "defend the castle" move, not a "this is the future" move. π
π boot_overload
For binary distributions and packaged applications, normal shared library loading semantics may not work. A custom loader may provide this method to use in place of, or to supplement, the standard XS load of Wx.dll (Wx.so).
The method MUST return true or false, depending on whether it has loaded Wx.dll (Wx.so).
For example, to load the core wxWidgets dlls before Wx is loaded:
sub boot_overload {
shift;
require DynaLoader;
for my $dll ( qw( base core adv ) ) {
next unless exists $Wx::dlls->{$dll} && $Wx::dlls->{$dll};
my $file = ( $Wx::wx_path ) ? $Wx::wx_path . '/' . $Wx::dlls->{$dll} : $Wx::dlls->{$dll};
my $libref = DynaLoader::dl_load_file($file, 0);
push(@DynaLoader::dl_librefs,$libref) if $libref;
# Dynaloader should take care of unloading
}
#------------ IMPORTANT ----------
return 0; # we have not loaded Wx
#---------------------------------
}
IMPORTANT section, do not skip π β that return 0; is marked IMPORTANT in the source itself. It means "we have not loaded Wx". Return values in this method are load-bearing. Literally.
Some packagers extract dlls at runtime, and then may attempt to remove them at application close. This may fail for Wx. For example, on MSWin the directory cleanup fails whilst on Linux the application will seg-fault on exit. Packagers may avoid this by loading Wx.dll (Wx.so) from a non standard location (perhaps a separate binary distribution of wx dlls) that is not removed at application exit.
For example:
sub boot_overload {
my $class = shift
require DynaLoader;
for my $dll ( qw( base core adv ) ) {
next unless exists $Wx::dlls->{$dll} && $Wx::dlls->{$dll};
my $file = ( $Wx::wx_path ) ? $Wx::wx_path . '/' . $Wx::dlls->{$dll} : $Wx::dlls->{$dll};
my $libref = DynaLoader::dl_load_file($file, 0);
push(@DynaLoader::dl_librefs,$libref) if $libref;
# Dynaloader should take care of unloading
}
package
DynaLoader;
my $file = $class->get_the_location_to_wx_xs_module;
#------------------------------------------
# From XSLoader
#------------------------------------------
my $module = 'Wx';
my $boots = "$module\::bootstrap";
my $bootname = "boot_$module";
$bootname =~ s/\W/_/g;
@DynaLoader::dl_require_symbols = ($bootname);
my $boot_symbol_ref;
my $libref = dl_load_file($file, 0) or do {
require Carp;
Carp::croak("Can't load '$file' for module $module: " . dl_error());
};
push(@DynaLoader::dl_librefs,$libref); # record loaded object
my @unresolved = dl_undef_symbols();
if (@unresolved) {
require Carp;
Carp::carp("Undefined symbols present after loading $file: @unresolved\n");
}
$boot_symbol_ref = dl_find_symbol($libref, $bootname) or do {
require Carp;
Carp::croak("Can't find '$bootname' symbol in $file\n");
};
push(@DynaLoader::dl_modules, $module); # record loaded module
my $xs = dl_install_xsub($boots, $boot_symbol_ref, $file);
push(@DynaLoader::dl_shared_objects, $file); # record files loaded
#------------ IMPORTANT ----------
return 1; # we have loaded Wx
#---------------------------------
}
That one's the full send β it goes all the way through the XSLoader dance and comes back with return 1; # we have loaded Wx. Two different return values, two different meanings. Chef's kiss. π
π Full Custom Loader Example π
Bestie. The whole thing, in one piece. A real loader from a real distribution, and it's honestly a serve:
################################################
# Custom loader for Wx distribution from
# http://www.wxperl.co.uk/repository
#
################################################
package Wx::Loader::Custom;
use strict;
use warnings;
our @ISA = qw( Wx::Loader::Standard );
$Wx::wx_binary_loader = __PACKAGE__ if !$Wx::wx_binary_loader;
sub loader_info { 'Linux PPM Distribution from http://www.wxperl.co.uk/repository'; }
sub boot_overload {
shift;
require DynaLoader;
for my $dll ( qw( base core adv ) ) {
next unless exists $Wx::dlls->{$dll} && $Wx::dlls->{$dll};
my $file = ( $Wx::wx_path ) ? $Wx::wx_path . '/' . $Wx::dlls->{$dll} : $Wx::dlls->{$dll};
my $libref = DynaLoader::dl_load_file($file, 0);
push(@DynaLoader::dl_librefs,$libref) if $libref;
# Dynaloader should take care of unloading
}
return 0;
}
# Allow legacy packaging call to override our load method
my( $load_fun ) = ( \&_load_dll );
sub _load_dll {
return unless exists $Wx::dlls->{$_[0]} && $Wx::dlls->{$_[0]};
my $dll = $Wx::dlls->{$_[0]};
$dll = $Wx::wx_path . '/' . $dll if $Wx::wx_path;
return Wx::_load_plugin( $dll );
}
sub external_set_load { $load_fun = $_[1] }
sub load_dll {
shift;
goto &$load_fun;
}
Notice how it does the polite loader-slot grab, gives you a real loader_info string, boots the base core adv dlls, returns 0 because it hasn't loaded Wx, and then keeps _load_dll around behind a goto &$load_fun so a legacy packaging call can still override the load method. That's range. That's versatility. That's main character energy. β¨π
that's the whole page, bestie β every flag, every method, every MUST, every deprecated warning, nothing skipped, nothing invented π«Ά
This was pulled from the perl docs, perl v5.42.3, dated 2026-08-20, section 3pm. Take care of your loaders and your loaders will take care of you. Mwah. πβ¨π
π¦ where this page comes from
- ubuntu stonking: libwx-perl 1:0.9932-10build2 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms