Class: Perl::Engine
- Inherits:
-
Object
- Object
- Perl::Engine
- Defined in:
- lib/perl/engine.rb
Overview
Manages an instance of the Perl interpreter. With #eval method you can execute Perl code and get the result in a Ruby object. Objects are serialized using YAML, both in the Ruby and Perl side.
Constant Summary collapse
- PerlFile =
File.join(File.dirname(__FILE__), "engine.pl")
Instance Method Summary collapse
-
#define_method(method_name, body) ⇒ Object
Defines a method in the Perl interpreter.
-
#eval(code) ⇒ Object
Executes the given code in the Perl interpreter.
-
#initialize ⇒ Engine
constructor
Creates a new instance of the Perl interpreter.
-
#invoke_method(method_name, *arguments) ⇒ Object
Invokes a method previously defined by #define_method.
-
#request(request, options = {}) ⇒ Object
:nodoc:.
-
#running? ⇒ Boolean
Check if the Perl interpreter is still alive.
-
#stop! ⇒ Object
Stop the Perl interpreter.
Constructor Details
#initialize ⇒ Engine
Creates a new instance of the Perl interpreter.
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/perl/engine.rb', line 26 def initialize writer = IO.pipe reader = IO.pipe @pid = fork do writer[1].close reader[0].close ENV["ENGINE_READER"] = writer[0].fileno.to_s ENV["ENGINE_WRITER"] = reader[1].fileno.to_s exec "perl", PerlFile end reader[1].close writer[0].close @stdin = reader[0] @stdout = writer[1] end |
Instance Method Details
#define_method(method_name, body) ⇒ Object
Defines a method in the Perl interpreter.
You can access to the arguments using the normal Perl syntax:
engine.define_method "add_two_values", "$_[0] + $_[1]"
114 115 116 |
# File 'lib/perl/engine.rb', line 114 def define_method(method_name, body) request "define_method", "name" => method_name.to_s, "body" => body.to_s, :generic_response => true end |
#eval(code) ⇒ Object
Executes the given code in the Perl interpreter. EngineNotRunningError will be raised if the interpreter is stopped.
The result will be returned in a Ruby object, using YAML to transport it. If an error is produced in the Perl interpreter the EngineCodeError exception will be raised, with the error message generated by Perl.
106 107 108 |
# File 'lib/perl/engine.rb', line 106 def eval(code) request :eval, "code" => code, :generic_response => true end |
#invoke_method(method_name, *arguments) ⇒ Object
Invokes a method previously defined by #define_method
Objects are passed to Perl using YAML. Everything that can be understood by YAML in both sides can be used as an argument.
121 122 123 |
# File 'lib/perl/engine.rb', line 121 def invoke_method(method_name, *arguments) request "invoke_method", "name" => method_name.to_s, "arguments" => arguments, :generic_response => true end |
#request(request, options = {}) ⇒ Object
:nodoc:
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/perl/engine.rb', line 71 def request(request, = {}) # :nodoc: raise EngineNotRunningError, "Engine is not running" unless @stdout and @stdin generic_response = .delete(:generic_response) data = { "request" => request.to_s }.merge!().to_yaml @stdout.print([data.length].pack("L") + data) data_length = @stdin.read(4).to_s raise EngineReadingError, "Can not read data" if data_length.length != 4 data_length = data_length.unpack("L").first data = @stdin.read(data_length) raise EngineReadingError, "Can not read data" if data.length != data_length response = YAML.load data if generic_response case response["status"] when "ok" response["result"] when "error" raise EngineCodeError, response["error"].chomp end else response end end |
#running? ⇒ Boolean
Check if the Perl interpreter is still alive
47 48 49 50 51 52 53 54 55 |
# File 'lib/perl/engine.rb', line 47 def running? return false unless @stdin and @stdout if IO.select [@stdin], [], [], 0 return false if @stdin.eof? end true end |
#stop! ⇒ Object
Stop the Perl interpreter
58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/perl/engine.rb', line 58 def stop! return false unless running? @stdin.close @stdout.close @stdin = @stdout = nil Process.kill "TERM", @pid Process.wait @pid true end |