<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">2016-11-28 11:58 GMT+01:00 Joaquin Ferrero <span dir="ltr"><<a href="mailto:explorer@joaquinferrero.com" target="_blank">explorer@joaquinferrero.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Â Â Buenos dÃas.<br>
<br>
  En la charla que nos dio dayer, vimos cómo seleccionar un comportamiento u otro según el S.O. en donde nos encontremos. Incluido la carga de módulos distintos para Linux/Windows.<br>
<br>
  Comenté que habÃa visto en CPAN diversas opciones para hacer eso mismo, sobre todo evitar tener que repetir el código<br>
<br>
if ($^O eq 'Win32') {<br>
<br>
  una y otra vez. La idea es tener una API común, y luego cada módulo, tendrá su interfaz propia de cada S.O.<br>
<br>
<br>
He encontrado varios ejemplos, y todos ellos muestran formas muy distintas de solventar la cuestión. Al final del mensaje pongo un listado con las lÃneas interesantes.<br>
<br>
<br>
Aquà explicaré la solución de Audio::Beep <<a href="https://metacpan.org/release/Audio-Beep" rel="noreferrer" target="_blank">https://metacpan.org/release/<wbr>Audio-Beep</a>>, que me parece el más corto y claro donde se puede ver esta técnica.<br>
<br>
<br>
En Beep.pm, dentro de new(), hay una lÃnea que busca por el mejor reproductor que exista en nuestro sistema:<br>
<br>
    $h{player} = _best_player();<br>
<br>
<br>
Dentro de _best_player() vemos cómo cargar el módulo correspondiente a nuestro S.O.:<br>
<br>
|sub| |_best_player {|<br>
|||my| |%os_modules| |= (|<br>
|||linux| |=> [|<br>
|||'Audio::Beep::Linux::beep'|<wbr>|,|<br>
|||'Audio::Beep::Linux::PP'||,<wbr>|<br>
|||],|<br>
|||MSWin32| |=> [|<br>
|||'Audio::Beep::Win32::API'||<wbr>,|<br>
|||],|<br>
|||freebsd| |=> [|<br>
|||'Audio::Beep::BSD::beep'||,<wbr>|<br>
|||],|<br>
|||);|<br>
||<br>
|||for| |my| |$mod| |( @{ ||$os_modules||{$^O} } ) {|<br>
|||if| |(||eval| |"require $mod"||) {|<br>
|||my| |$player| |= ||$mod||->new();|<br>
|||return| |$player| |if| |defined| |$player||;|<br>
|||}|<br>
|||}|<br>
|||return||;|<br>
|}|<br>
<br>
  Primero carga un hash con todos los módulos de la distribución.<br>
<br>
  Luego, en el bucle for(), extrae los módulos correspondientes al<br>
  S.O. en que se está ejecutando.<br>
<br>
  Hace un eval "requiere ...", y regresa si la inicialización ha sido<br>
  correcta.<br>
<br>
Y dentro de los módulos Audio::Beep::Linux::beep, Audio::Beep::Linux::PP, Audio::Beep::Win32::API y Audio::Beep::BSD::beep, lo único que hay son tres funciones básicas:<br>
<br>
  new(), para la inicialización,<br>
  play(), para tocar una nota, y<br>
  rest(), para hacer una pausa<br>
<br>
El programa principal solo tiene que hacer llamadas basadas en esa API:<br>
<br>
$self->player->play( _pitch(\%p), _duration(\%p) );<br>
<br>
<br>
<br>
Resto de distribuciones que he encontrado extrayendo las lÃneas interesantes:<br>
<br>
Net::Routing <<a href="https://metacpan.org/release/Net-Routing" rel="noreferrer" target="_blank">https://metacpan.org/release/<wbr>Net-Routing</a>> - manage route entries on Operating Systems<br>
<br>
  BEGIN {<br>
    if ($^O eq 'linux') {<br>
     return $_routing_module = "Net::Routing::Linux";<br>
    }<br>
    elsif ($^O eq 'freebsd') {<br>
     return $_routing_module = "Net::Routing::FreeBSD";<br>
    }<br>
    elsif ($^O eq 'netbsd') {<br>
     return $_routing_module = "Net::Routing::NetBSD";<br>
    }<br>
    elsif ($^O eq 'darwin') {<br>
     return $_routing_module = "Net::Routing::Darwin";<br>
    }<br>
    #elsif ($^O eq 'MSWin32') {<br>
    #  return $_routing_module = "Net::Routing::MSWin32";<br>
    #}<br>
    #elsif ($^O eq 'openbsd') {<br>
    #  return $_routing_module = "Net::Routing::OpenBSD";<br>
    #}<br>
      die("[-] Net::Routing: Operating System not supported: $^O\n");<br>
  }<br>
    sub new {<br>
    my $self = shift->SUPER::new(<br>
     path => [ qw(/bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin) ],<br>
     lc_all => 'en_GB.UTF-8',<br>
     target => NR_TARGET_ALL(),<br>
     family => NR_FAMILY_INET4(),<br>
     @_,<br>
    );<br>
      $self->path([ @{$self->path}, split(':', $ENV{PATH}) ]);<br>
      eval("use $_routing_module;");<br>
    if ($@) {<br>
     chomp($@);<br>
     $Error = "unable to load routing module [$_routing_module]: $@";<br>
     return;<br>
    }<br>
<br>
Sys::Ramdisk <<a href="https://metacpan.org/release/Sys-Ramdisk" rel="noreferrer" target="_blank">https://metacpan.org/release/<wbr>Sys-Ramdisk</a>> - Create and nuke RAM disks on various systems<br>
<br>
Unix::Uptime <<a href="https://metacpan.org/release/Unix-Uptime" rel="noreferrer" target="_blank">https://metacpan.org/release/<wbr>Unix-Uptime</a>> - Determine the current uptime, in seconds, and load averages, across different *NIX architectures<br>
<br>
  my $module = $modules{$^O}<br>
    or die "Operating system type $^O is currently unsupported";<br>
    require "Unix/Uptime/$<a href="http://module.pm" rel="noreferrer" target="_blank">module.pm</a>";<br>
  our @ISA = ("Unix::Uptime::$module");<br>
<br>
IO::Async <<a href="https://metacpan.org/release/IO-Async" rel="noreferrer" target="_blank">https://metacpan.org/release/<wbr>IO-Async</a>> - Asynchronous event-driven programming<br>
<br>
  if( eval { require "IO/Async/OS/$^O.pm" } ) {<br>
    @ISA = "IO::Async::OS::$^O";<br>
  }<br>
<br>
System::Info <<a href="https://metacpan.org/release/System-Info" rel="noreferrer" target="_blank">https://metacpan.org/release/<wbr>System-Info</a>> - Factory for system specific information objects<br>
<br>
  sub new {<br>
    my $factory = shift;<br>
       $^O =~ m/aix/i        and return System::Info::AIX->new;<br>
    $^O =~ m/bsd/i        and return System::Info::BSD->new;<br>
    $^O =~ m/cygwin/i      and return System::Info::Cygwin->new;<br>
    $^O =~ m/darwin/i      and return System::Info::Darwin->new;<br>
    $^O =~ m/haiku/       and return System::Info::Haiku->new;<br>
    $^O =~ m/hp-?ux/i      and return System::Info::HPUX->new;<br>
    $^O =~ m/irix/i       and return System::Info::Irix->new;<br>
    $^O =~ m/linux/i       and return System::Info::Linux->new;<br>
    $^O =~ m/solaris|sunos|osf/i and return System::Info::Solaris->new;<br>
    $^O =~ m/VMS/        and return System::Info::VMS->new;<br>
    $^O =~ m/mswin32|windows/i  and return System::Info::Windows->new;<br>
       return System::Info::Generic->new;<br>
    }<br>
<br>
App::Slaughter <<a href="https://metacpan.org/release/App-Slaughter" rel="noreferrer" target="_blank">https://metacpan.org/release/<wbr>App-Slaughter</a>> - Perl Automation Tool Helper<br>
<br>
Parse::Netstat <<a href="https://metacpan.org/release/Parse-Netstat" rel="noreferrer" target="_blank">https://metacpan.org/release/<wbr>Parse-Netstat</a>> - Parse the output of "netstat" command<br>
<br>
    if ($flavor eq 'linux') {<br>
      require Parse::Netstat::linux;<br>
      Parse::Netstat::linux::parse_n<wbr>etstat(<br>
        output=>$output, tcp=>$tcp, udp=>$udp, unix=>$unix);<br>
    } elsif ($flavor eq 'freebsd') {<br>
      require Parse::Netstat::freebsd;<br>
      Parse::Netstat::freebsd::parse<wbr>_netstat(<br>
        output=>$output, tcp=>$tcp, udp=>$udp, unix=>$unix);<br>
    } elsif ($flavor eq 'solaris') {<br>
      require Parse::Netstat::solaris;<br>
      Parse::Netstat::solaris::parse<wbr>_netstat(<br>
        output=>$output, tcp=>$tcp, udp=>$udp, unix=>$unix);<br>
    } elsif ($flavor eq 'win32') {<br>
      require Parse::Netstat::win32;<br>
      Parse::Netstat::win32::parse_n<wbr>etstat(<br>
        output=>$output, tcp=>$tcp, udp=>$udp);<br>
    } else {<br>
      return [400, "Unknown flavor '$flavor', please see --help"];<br>
    }<br>
<br>
Sys::Filesystem <<a href="https://metacpan.org/release/Sys-Filesystem" rel="noreferrer" target="_blank">https://metacpan.org/release/<wbr>Sys-Filesystem</a>> - Retrieve list of filesystems and their properties<br>
<br>
  [ @query_order = map { __PACKAGE__ . '::' . $_ } ( ucfirst( lc $^O ), $^O =~ m/Win32/i ? 'Win32' : 'Unix', 'Dummy' ) ]<br>
<br>
En esta última distribución, se usa Module::Pluggable, para cargar el módulo como si fuera un "plugin" o complemento de la propia distribución.<br>
<br>
Saludos,<span class="HOEnZb"><font color="#888888"><br>
</font></span><br></blockquote><div><br></div><div>Muchas gracias JoaquÃn. Voy a experimentar con estas sugerencias y actualizaré mi ejemplo :-)<br><br></div><div>Un saludo, <br></div></div></div></div>