User Tools

Site Tools



This shows you the differences between two versions of the page.

Link to this comparison view

using_perl [2006/08/29 20:18] (current)
Line 1: Line 1:
 +======Using the inbuilt embedded perl functions======
 +Let me start out by saying that it is possible, and still advisable in
 +most cases to use the [[exec command|EXEC]] command to do many of the things you want
 +from an external scripting language. The external script will run as a
 +separate process which will save you performance problems and memory.
 +The reason you might want to use the $[[perl function|perl]]*()
 +functions are in those situations where you need data to be returned
 +from the perl script or if you need it to do something within the epic
 +environment from that script. These mechanisms are faster and much more
 +stable in these functions than trying to do the same thing with an
 +/[[exec command|exec]].
 +The perl environment can be used at many levels, from being a helper
 +to your irc script to almost entirely driving your script from within
 +perl. Most perl modules are available for use from within the perl
 +environment,​ but those that don't return control to your script are
 +unlikely to be useful. It is also makes it possible to alter epics
 +process environment,​ such as redefining signals, forking and making
 +other random system calls, which is not always a good idea.
 +The embedded perl script starts with a call to $[[perl
 +function|perl]](expression). When $[[perl function|perl]]() is called,
 +the perl environment is initialized and the expression is evaluated.
 +Typically what you want is an expression that loads a script or defines
 +subroutines for use from your epic environment with the $[[perlcall]]()
 +At this point, the $[[perlcall]]() and $[[perlxcall]]() functions can be used
 +to call whatever subroutines have been defined. $[[perlcall]](sub any text)
 +calls the perl subroutine "​sub"​ in scalar context with "any text" as its first
 +argument. More complex calls involving Karll [[arrays]](7) are possible with
 +Three new subroutines are available from within the perl environment:​
 +EPIC::cmd evaluates its arguments as irc commands, returning nothing.
 +EPIC::eval evaluates its arguments as if they were applied to /[[eval]],
 +also returning nothing. EPIC::expr evaluates its arguments as epic
 +[[expressions]](7),​ returning the results of those expressions.
 +The exact difference between cmd and eval is that anything passed to
 +eval is subject to Epics parsing rules while anything passed to cmd is
 +not. This is not unlike the difference between single and double quoting
 +in perl.
 +You can use these to "​drive"​ your script from perl, although, if you are
 +going to do this with a long running script, it is highly recommended
 +that you make calls to EPIC::​eval("​pause 1") liberally.
 +You should not call the EPIC functions from within %SIG signal handlers
 +other than $SIG{__WARN__} and $SIG{__DIE__}. Epics internals are likely
 +to be unable to handle such behavior.
 +From the perl environment,​ hooks, aliases and other miscellaneous
 +settings can be changed via the EPIC functions:
 +|EPIC::​eval('​on hook * @perlcall(sub $*)'​) ​ |Sets up a callback from a hook.        |
 +|EPIC::​eval('​alias foo @perlcall(sub $*)'​) ​ |Defines an alias with a callback. ​     |
 +|EPIC::​eval('​echo $foo'​) ​                   |Echoes the epic variable $foo.         |
 +|EPIC::cmd ('echo $foo'​) ​                   |Echoes the text "​$foo"​. ​               |
 +|EPIC::cmd ("echo $foo"​) ​                   |Echoes the perl variable $foo.         |
 +|EPIC::​expr('​var'​) ​                         |Returns value of variable var.         |
 +|EPIC::​expr('​aliasctl(assign get var)'​) ​    |Also returns variable var.             |
 +|EPIC::​expr('​myalias(x)'​) ​                  ​|Calls epic alias myalias(). ​           |
 +|EPIC::​expr('​jot(0 99)'​) ​                   |Calls epic function jot(0 99).         |
 +|EPIC::​expr('​1+2*3'​) ​                       |How to use epic for math.              |
 +|EPIC::​expr('​perl(EPIC::​expr "​1+2*3"​)'​) ​    |One last facetious example. ​ :-)       |
 +To fully understand what is possible with EPIC::expr, you should read
 +[[Expressions]](7). Briefly, you can retrieve anything from within the
 +epic environment with it, and do many things as well. Exceptions to
 +this are covered by EPIC::cmd and EPIC::eval, which execute commands,
 +for which you should read [[Programming]](7).
 +=====Miscellaneous things to be aware of:=====
 +By default, perl warnings and errors will be yelled and are trapable
 +with the on(5) yell hook or from perl with the $SIG{__DIE__} and
 +$SIG{__WARN__} hooks. This is accomplished with EPIC::yell. This you can
 +use for your own purposes, but it's better to use EPIC::cmd "echo ...".
 +$[[perlcall]]() and $[[perlxcall]]() will return a zero length string if they
 +are called while the perl environment is uninitialized or if the sub is
 +undefined. You can use this from within an epic script to trigger an autoload
 +of a perl subroutine for eg.
 +In terms of performance,​ __perl*call__() are pretty damn fast, but the
 +overhead of switching to perlspace takes an order of magnitude longer than
 +making the same call from perlspace. To gain performance,​ you should avoid
 +switching universes as much as possible. The EPIC::* functions all take and
 +return lists. You will probably find that combining many calls into one makes
 +them a lot faster.
 +While it is possible to write a script almost entirely in perl, with calls to
 +the EPIC functions, the script will need to be loaded with a call to
 +$[[perl function|perl]]() from an epic script or with a command.
 +The EPIC::* functions will execute within the context that called
 +$[[perl function|perl]]*() so it is possible to manipulate epic variables local to that
 +While perl is quite capable of assigning any string of characters to a
 +variable, epic is not. Any perl string containing a null character will
 +be silently truncated when it is assigned to an epic variable.
 +Using perl for non-trivial networking is likely to be trickier than under pure
 +perl. Not only does your code have to maintain its sockets, but it has to give
 +epic enough cpu time to maintain its own. This can be done by including all of
 +epics file descriptors in a perl select() call and calling EPIC::eval "pause 1"
 +each time select returns one of them. There currently is no definitive way to
 +obtain these descriptors,​ but they are included in some hooks such as [[on send
 +to server|send_to_server]] and [[on dcc raw|dcc_raw]].
 +Alternatives to the above are:
 +  * Use epic for networking with the raw dcc interface.
 +  * Use an external script to handle the request, via the exec interface.
 +  * Keep your perl networking code short and sweet.
 +"alias perl unless (functioncall()) {@perl($*)}"​ sets up a /[[perl
 +command|PERL]] command. The arguments will be executed within the
 +embedded perl environment. You may also want to use this alias for
 +calling an external interpreter,​ which is why there is no inbuilt
 +/[[perl command|PERL]] command. The choice is yours.
using_perl.txt ยท Last modified: 2006/08/29 20:18 (external edit)