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

Line ending issue with Mercurial or Visual Studio -

java - Jtable duplicate Rows -

java - Run a .jar on Heroku -