p = new Perl('Sys::Hostname', 'Test::Harness')In addition to creating an interpreter, this will also include the libraries you pass to the Perl constructor, which is equivalent to use Sys::Hostname; use Test::Harness. You can always include libraries explicitly by using p.eval('use Sys::Hostname; use Test::Harness'). There is also another way to do this: p.use('Sys::Hostname', 'Test::Harness'). As you can see, TMTOWTDI.
Note: If the statements above fail on you saying something about libraries not found in the search path, you need to make sure the modules PerlConnect uses, JS.pm and PerlConnect.pm live in some directory accessible from the search path. Search path can be set by adjusting the value of PERLLIB and PERL5LIB environment variables. See installation for more details.
Note: Despite the illusion p = new Perl(...) syntax might create, there is actually only one version of the Perl interpreter running. I.e. if you create two interpreters like this:
p = new Perl; q = new Perl;Now you'll see that q["$a"] will give you $a's value from p.
p.eval("$a='ha-'x20");
Naturally, you will want to look at the result of your function calls and eval statements. Suppose, you do something like this:
line = p.eval("'-' x 80")Perl's eval returns the last statement evaluated, unless you explicitly say return. So now line contains 80 dashes. You can do similar things with non-scalar data types:
p.use('Time::gmtime');assigns a Perl array to t. You can print t, use the for/in syntax to walk through it, compute its length, etc. You can read and assign to individual elements using the standard syntax. However, PerlValues, that is, the value we get from Perl, don't support all the standard operations, for instance, don't expect t.reverse() to work. Hashes can also be returned from Perl:
t = p.eval('Time::gmtime::gmtime') // returns [49,0,4,24,6,98,5,204,0]
info=p.eval("{ver=>$], pid=>$$}")Now you can look at individual hash keys like this:
info["ver"] or info.pidSuppose you want to use Perl to perform pattern-based string replacement. Here's how you can do it from JavaScript:
p.eval("\and now
sub perl_replace(){\
my($string, $find, $replace) = @_;\
eval(\"\\$string =~ s/$find/$replace/g;\");\
return $string;\
}"
);
p.perl_replace('Quick brown fox jumped over a lazy dog', 'dog', 'rhino')produces what you'd expect.
You can use the same syntax to call procedures defined in modules other than main. The example with gmtime can be rewritten like this:
p.use('Time::gmtime');You can reference variables exported by modules other than main like this:
t = p.Time.gmtime.gmtime() // returns [49,0,4,24,6,98,5,204,0]
a=p.Foo.$bar or a=p.Foo["$bar"] orEach of the above statements return either an immediate JS value, for scalar types, or a PerlValue for compound types. a.type contains the type of the PerlValue in a. This may change because we may end up separating Perl hashes and arrays into separate classes.
a=p.Foo["@bar"]or a=p.Foo["%bar"]
use JS;and now you can do something like this:
$js = new JS();
$js->eval(q/Note: Please see test.js and test.pl, test scripts that test and demonstrate various features of PerlConnect and JS.pm, respectively. They will help get you started.Object o = {};/);
o.a = 'p';
o.b = 'q';
return o;
Object | What it does |
Perl | Perl Interpreter Object. Its prototype type is PerlModule, it corresponds to main::. Supports eval, call, use. |
PerlModule | Implements JS-like syntax for Perl modules. Doesn't export provide any methods. path property shows the name of the Perl module the object represents. |
PerlValue | Represents a value returned from eval, call, or obtained by using the subscript notation (p.Foo["@bar"]). Its Perl type is stored in the type property. |
See comments in the code, jsperl.c and JS.pm for more
info.
Note: PerlConnect heavily relies on PerlConnect.pm, which
does some background magic for it. PerlConnect.pm should not be
used. Use JS.pm instead.
The following Perl packages (objects) are implemented:
Package | What it contains |
JS | Doesn't do anything in particular at this point except defining a constructor. So one can say $js = new JS(), which will create a new runtime, add a context to it and return that Context. JS also defines a bunch of private functions called from C by PerlConnect. They are not exposed by default, but pushed onto @EXPORT_OK array instead. |
JS::Runtime | Corresponds to JSRuntime* struct. Provides a constructor and destructor. The destructor is invoked automatically, so you don't have to worry about Runtime deallocation. Constructor syntax is the following: $rt = new JS::Runtime(10_000), where the parameter is the same number you pass to JS_NewRuntime. There are many private functions created in JS.xs that are not exported by default. |
JS::Context | Corresponds to JSContext* struct. Provides a constructor and destructor. The destructor is invoked automatically, so you don't have to worry about Context deallocation. Constructor syntax is the following: $rt = new JS::Context($rt, 1_000), where the parameter is the same number you pass to JS_NewContext. There are many private functions created in JS.xs that are not exported by default. |
JS::Object | Corresponds to JSObject* struct. There is not that much here yet. This object is intended as a wrapper around the JSObject* struct. Support for tying hashes and possibly arrays with JS::Objects is coming. |
[JS::Array] | I am not quite sure if this is needed. One might probably get away with just JS::Object defined. If it's implemented, it will be very much similar to JS::Object above. |
All the modules above follow the convention of storing the variable they return in the $this variable of the current class. So $JS::Context::this will always be the last context created. Currently, this is where JS API function that require contexts get it.
JS also builds a DLL, JS.dll which is supposed to reside where Perl's DynaLoader can find it. On my machine I put it under c:\perl\lib\auto\JS\JS.dll. You can also put it in c:\perl\lib\. You can probably adjust PERLLIB to achieve the desired result. See Perl's DynaLoader documentation for more info on how dynamic libraries are found.
On UNIX:
We are currently working on a UNIX makefile. Please contact
me for more details.