using_perl
no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
| — | using_perl [2006/08/29 20:18] (current) – created - external edit 127.0.0.1 | ||
|---|---|---|---|
| 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, | ||
| + | unlikely to be useful. It is also makes it possible to alter epics | ||
| + | process environment, | ||
| + | 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]]() | ||
| + | functions. | ||
| + | |||
| + | 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 " | ||
| + | argument. More complex calls involving Karll [[arrays]](7) are possible with | ||
| + | $[[perlxcall]](). | ||
| + | |||
| + | 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), | ||
| + | |||
| + | 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 " | ||
| + | going to do this with a long running script, it is highly recommended | ||
| + | that you make calls to EPIC:: | ||
| + | |||
| + | 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, | ||
| + | settings can be changed via the EPIC functions: | ||
| + | |||
| + | |EPIC:: | ||
| + | |EPIC:: | ||
| + | |EPIC:: | ||
| + | |EPIC::cmd ('echo $foo' | ||
| + | |EPIC::cmd ("echo $foo" | ||
| + | |EPIC:: | ||
| + | |EPIC:: | ||
| + | |EPIC:: | ||
| + | |EPIC:: | ||
| + | |EPIC:: | ||
| + | |EPIC:: | ||
| + | |||
| + | 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, | ||
| + | overhead of switching to perlspace takes an order of magnitude longer than | ||
| + | making the same call from perlspace. To gain performance, | ||
| + | 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 | ||
| + | context. | ||
| + | |||
| + | 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, | ||
| + | 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($*)}" | ||
| + | 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, | ||
| + | /[[perl command|PERL]] command. The choice is yours. | ||
using_perl.txt · Last modified: 2006/08/29 20:18 by 127.0.0.1
