class - How to handle external sub prototype with local AUTOLOAD in Perl -


i'm having issue following scenario. i'm writting class uses autoload somtimes call functions module (not mine). other module use few functions prototypes defined. 1 example this:

sub external_sub (\@$) { ... } 

those functions work correctly when imported directly module, calls following:

my @arr = (1..10); external_sub(@arr, 'something else'); 

now, problem have when requiring external module class @ run time , importing function, can't find way pass right arguments it.

inside autoload function, count on @_ only, , don't know if there's way in perl tell apart array passed first argument autoload. so, inside autoload, options can think far redirect call are:

no strict 'refs'; $sym = *{"externalmodule\::$called_sub"}; *$autoload = $sym; goto &$autoload; 

...or like:

no strict 'refs'; return &{"externalmodule\::$called_sub"}(@_); 

or several similar things using symbol table. however, problem how pass arguments call. if in code have:

package main;  use strict; use mymodule qw(:some_external_subs); # import *names decide later modules take actual code refs  # here have imported sub 'external_sub' symbol won't loaded until mymodule::autoload decides external module use import code function:  @arr = ('some', 'values');  $result = external_sub(@arr, 'other_argument'); 

then, that's point autoload in module require external module , pass call actual prototyped sub external_sub(\@$). problem pass received arguments @_, @arr , 'other_argument' part of single list.

is there way resolve situation this? there way detect original arguments before becoming @_?

keep in mind don't have control on external module , fact uses prototyped function.

thanks in advance comments!

to having similar problem, i've found far:

  1. you can define prototypes @ compile time, otherwise ignored.

  2. if know name of function @ compile time plan on loading code symbol later (at run time), can define prototype without code:

    sub some_sub(\@$); 
  3. if don't know name of function can dynamically ar compile time, can use scalar::util::set_prototype declare local prototype only:

    package mymodule; use strict; use scalar::util qw(set_prototype); $protos;  begin { # compile time         @functions;          # imagine load here @functions hashrefs containing name , proto values.          no strict 'refs'         $i (@functions) {             # defines prototype without defining sub             set_prototype \&{"mymodule::$i->{name}"}, $i->{proto};             # if want recall name/proto later in autoload:             $protos->{$i->{name}} = $i->{proto};         } } 

since declaration of prototype ready not definition of subroutine itself, when subroutine called first time trigger autoload subroutine, can proceed assign actual coderef symbol. coderef use must have same prototype 1 declared name or receive error of prototype mismatch. it's possible assign same prototype coderef using set prototype if necessary, before assigning coderef real symbol.

for example:

sub autoload {     our $autoload;     $name = substr $autoload, rindex($autoload, ':') + 1;      # here process , decide i'll call othermodule::some_sub name in $autoload      no strict 'refs';     $coderef = *{"othermodule::some_sub"}{code};     # prototypes must match!     unless (defined(prototype $coderef) , $protos->{$name} eq prototype $coderef) {         set_prototype(\&$coderef, $protos->{$name});     }     *$autoload = $coderef;     goto &$autoload; } 

if else knows of actual way alter prototypes @ runtime , have them work expected after that, i'll more happy know it!

meanwhile, hope helps facing similar situation in future.


Comments

Popular posts from this blog

java - Run a .jar on Heroku -

java - Jtable duplicate Rows -

validation - How to pass paramaters like unix into windows batch file -