Tharg has asked for the wisdom of the Perl Monks concerning the following question:

I want a function which uses Barcode::DataMatrix in a safe container. So then I can "safe"ly reval code passed as a sting, which might contain this function which uses Barcode::DataMatrix. Currently I always get :
(in cleanup) Can't locate object method "new" via package "Barcode::Da +taMatrix" (perhaps you forgot to load "Barcode::DataMatrix"?)
I hope that makes sense. I'm right on the edge of my skill level here. Here is some code. I've been trying all kinds of combinations in the share_from, share, etc. I'm sure they're wrong, for a start, but I haven't figured out the right way.
use strict; use warnings; use Barcode::DataMatrix; use Data::Dumper; use Safe; sub DataMatrix2d{ my( $value ) = @_; my $mat = Barcode::DataMatrix->new()->barcode( $value ); return $mat; } my @safeops = ( qw( null stub scalar const padany lineseq leaveeval rv2gv ), + # Basic variable IO and traversal qw( lt i_lt gt i_gt le i_le ge i_ge eq i_eq ne i_ne ncmp i_ncmp sl +t sgt sle sge seq sne scmp ), # Comparators qw( preinc i_preinc predec i_predec postinc i_postinc postdec i_po +stdec int hex oct abs pow multiply i_multiply divide i_divide modulo +i_modulo add i_add subtract i_subtract ), # Base math qw( left_shift right_shift bit_and bit_xor bit_or negate i_negate +not complement ), # Binary math qw( match split qr ), # Regex qw( cond_expr flip flop andassign orassign and or xor ), + # Conditionals qw( atan2 sin cos exp log sqrt rand srand ), + # Advanced math qw( rv2cv entersub leavesub pushmark list rv2sv anoncode refgen rv +2av aassign rv2hv helem sassign exists concat subst length return ent +er leave ) # XXX ); my($safefuncs) = new Safe; $safefuncs->permit_only( @safeops ); $safefuncs->share( 'Barcode::DataMatrix' ); $safefuncs->share_from('main', [ 'DataMatrix2d' ]); my $functiontext = 'sub{my($R)=@_;$R->{AA}=DataMatrix2d("001")}'; my $func = $safefuncs->reval( $functiontext ); if( ref( $func ) ne 'CODE' ){ print "Not a code ref"; exit; } my $data = {}; my $ret = $func->( $data ); if( ref( $ret ) ne 'ARRAY' ){ print "Failed"; exit; } printf( "%s\n", Dumper( $ret ) );
Edit : For any future googlers : I went with Safe::Hole in the end and it seems to be doing what I need.
  • Comment on Safe.pm, Barcode::DataMatrix, Can't locate object method "new" via package "Barcode::DataMatrix"
  • Select or Download Code

Replies are listed 'Best First'.
Re: Safe.pm, Barcode::DataMatrix, Can't locate object method "new" via package "Barcode::DataMatrix"
by stevieb (Canon) on Jul 19, 2015 at 14:50 UTC

    Are you *sure* this is the code you're running? When I run it, I get "Not a coderef" (after installing Barcode::DataMatrix)

    That error is caused either when you call a legit method on a class/object, but you haven't use Barcode::DataMatrix; (but you have), or you've loaded the module, but the method doesn't exist (in this case it does). This is often caused by a typo... like typing new() as nw() by accident.

    Test this yourself with this tiny sample and see what happens...

    use strict; use warnings; use Barcode::DataMatrix; use Safe; my $mat = Barcode::DataMatrix->new()->barcode( 1 ); print $mat;

    You should get similar output to this:

    $ ./bc.pl ARRAY(0x1960758)
      Yeah, I just copy / pasted it direct from here again and re-tested :
      C:\Users\XX\TestSafe>perl TestSafe.pl (in cleanup) Can't locate object method "new" via package "Bar +code::DataMatrix" (perhaps you forgot to load "Barcode::DataMatrix"?) + at TestSafe.pl line 13. Failed
      This 'snippet' is just a stripped-down-for-posting version of the actual code, but it gives me the same error.
        at TestSafe.pl line 13
        That seems to be the error from your own code - have you tested the sample code that stevieb gave you?
      Yeah that's what I get if I don't use the safe compartment (using your code) ... :
      C:\Users\XX\TestSafe>teststeve.pl ARRAY(0x37c520) C:\Users\XX\TestSafe>
      Using my DataMatrix2d function without putting it in a string and using reval on it etc. :
      C:\Users\XX\TestSafe>perl TestFunc.pl ARRAY(0x51c520) C:\Users\XX\TestSafe>
Re: Safe.pm, Barcode::DataMatrix, Can't locate object method "new" via package "Barcode::DataMatrix"
by tangent (Parson) on Jul 19, 2015 at 15:59 UTC
    From looking at the docs for Safe I don't think you are passing the correct arguments:
    $safefuncs->share( 'Barcode::DataMatrix' ); $safefuncs->share_from('main', [ 'DataMatrix2d' ]);
    'Barcode::DataMatrix' is being treated as a function name. You could try:
    $safefuncs->share_from( 'Barcode::DataMatrix', \@safeops ); $safefuncs->share_from( 'main', [ 'DataMatrix2d' ]);
    From the docs:
    share (NAME, ...)
    This shares the variable(s) in the argument list with the compartment... Each NAME must be the name of a non-lexical variable, typically with the leading type identifier included. A bareword is treated as a function name.
    share_from (PACKAGE, ARRAYREF)
    This method is similar to share() but allows you to explicitly name the package that symbols should be shared from. The symbol names (including type characters) are supplied as an array reference.
      No luck, I'm pretty sure \@safeops doesn't belong there (they are opcodes). I'm also sure the wrong args there - I've tried all sorts of combinations and the ones pasted above are just what I had in at that time. Most things I've tried give exactly the same errors / warnings. However I tried this (which I do not claim to understand, I'm just bashing the keyboard) :
      $safefuncs->share_from('main', [ 'DataMatrix2d', 'Barcode::DataMatrix: +:new' ]);
      and got a new error / warning :
      C:\Users\XX\TestSafe>perl TestSafe.pl Can't locate package Moose::Object for @Barcode::DataMatrix::ISA at Te +stSafe.pl line 13. (in cleanup) Undefined subroutine &Barcode::DataMatrix::new ca +lled at TestSafe.pl line 13.
        What about:
        $safefuncs->share_from( 'Barcode::DataMatrix', ['new','barcode'] );
Re: Safe.pm, Barcode::DataMatrix, Can't locate object method "new" via package "Barcode::DataMatrix"
by 1nickt (Canon) on Jul 19, 2015 at 21:08 UTC

    Have you checked to see that Safe.pm works correctly with your perl on your platform? Lots of errors on the CPAN testers matrix ...

    The way forward always starts with a minimal test.