Happy Newton's Birthday, monks!

I have decided to give myself the winter solstice present of picking up Lua, with an intent to use it as a quick embedded scripting language (somewhat silly from Perl, I know, but I plan to also use the same Lua code elsewhere). In doing so, I have run into a situation with namespaces that I think may actually require string eval for the first time in >8 years of Perl, which causes my codesmell sensors to go haywire, and thus, I am seeking your sage advice.

Essentially, I want to write a wrapper module around Inline::Lua which will facilitate config information (paths, file loading, etc) and provide a simple OO interface of ->load( 'module' ) and ->run( 'module', 'sub', @args ) However, for future-proofing, it is desirable to load each Lua module's symbols into their own namespace (package), indexed by Lua module name, so that collisions between symbols don't take place when loading multiple Lua modules.

  1. While this seems silly, almost like the varvar/symbolic reference issue, the ideal way would be to have dynamic package Foo::$bar; available, I was unable to do so, and ended up with an eval EXPR in the ->load() method, which is essentially forced upon me, due to the way that Inline crams subs into the current package (not that that is inherently a bad thing, it's really ideal for Inline, just not for this application). So, first, is there a way to avoid the string eval in the ->load() method below?
  2. Also, in trying countless ways to directly reference the loaded sub symbolically via something along the lines of:
    local *func = $main::{"Lua::${modname}::${funcname}"}
    I have been unable to get a handle to it from the ->run() method. Thus, is there also a way to avoid this, and get rid of the second string eval?

    Question 2 has kindly been sorted by kennethk.

Replacing one or both with a block eval would be ideal. While the code below does "work" (I'll be adding further error checking, of course), it still causes me no small consternation in thinking that there is a better way to do it.

Thus, I throw myself upon the mercy of the monks during this fine Kwanzaa season. Thank you ever so much.

(NB: Inline::Lua may be difficult to install properly; but it should not be necessary to install to simply examine the code.)

----------- Lua.pm ---------------

package Lua; use strict; use warnings; use Carp qw( croak ); #use Inline; my $luadir = '.'; sub new { my( $class ) = @_; my $self = {}; return( bless( $self, $class ) ); } sub load { my( $self, $module ) = @_; my $src_file = $module . '.lua' unless( $module =~ m/.*\.lua$/ ); my $path = path_join( $luadir, $src_file ); open( my $fd, '<', $path ) or warn "$src_file is inaccessible" and return; my $luacode = do { local $/; <$fd> }; close( $fd ); ####################################################### my $code = sprintf( 'package Lua::%s;' . 'use Inline;' . 'Inline->bind( Lua => $luacode );' . 'return( grep { ! /^BEGIN$/ } keys %%Lua::%s:: + )', $module, $module ); my @symbols = eval $code; package Lua; chomp $@ if( $@ ); warn "Error compiling $path: '$@'" and return if( $@ ); ####################################################### return( @symbols ); } sub run { my( $self, $module, $funcname, @args ) = @_; ###################################################### my $sub = sprintf( 'Lua::%s::%s( @args );', $module, $funcname ); my @retval = eval $sub; chomp $@ if( $@ ); warn "Error executing $module::$funcname: $@" and return if( $@ ); ###################################################### return( @retval ); } sub path_join { my $pathchar = ( $^O eq 'MSWin32' ) ? "\\" : '/'; return( join( $pathchar, @_ ) ); } 1; __END__

-------- lua.pl --------

#!/usr/bin/perl use strict; use warnings; use lib '.'; use Lua; my $lua = Lua->new(); my @symbols = $lua->load( 'foo' ); $lua->run( 'foo', 'Greet', 'grandma', 'pie' ); __END__

----------- foo.lua -------------

function Greet( name, treat ) print( "Hello, " .. name .. ". Would you like some " .. treat .. +"?\n" ) end

In reply to Inline::* and string eval -- Have I found a place where it might actually be necessary? by Luftkissenboot

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.