开发者

How can you interact with Perl programs from Ruby?

It's my understanding that there's no "bridge" between Ruby and Perl to let you开发者_StackOverflow call into Perl functions directly from Ruby. It's also my understanding that to call a Perl program from Ruby, you simply put it in backticks(i.e. result = `./helloWorld.pl`). However, this doesn't allow interaction with the Perl program(i.e. you can't interact with prompts or provide input). My quesitons are as follows:

  1. Is there any way to provide input to Perl programs from Ruby(aside from arguments)?

  2. Am I wrong that there is no bridge between Ruby and Perl? Interacting with a program's stdin seems like the wrong way to go when navigating prompts, and the programs I'm dealing with are well-designed and have libraries with the appropriate Perl functions in them.


There's the Inline::Ruby module, though I don't have any direct experience with it that I can share.

EDIT: I did try it out last night -- here's the review: Inline::Ruby was last updated in 2002, when v5.6 was the latest stable release. Docs say it has only been tested on Linux; I was trying to use it with v5.10.1 on Cygwin. Got it to build after some hacking of the XS/C code that comes with the module. Passed some unit tests but failed others. Seemed to import Ruby class's into Perl's namespace ok but was less successful importing standalone functions. Summary: if you need a quick and dirty bridge for Perl and Ruby, Inline::Ruby will probably disappoint you. If you have the patience to figure out how to build the module on your system, and to massage your Ruby code to work with the module, you could find it useful.


Use Ruby's exec()

rubypl.rb

#!/usr/bin/ruby -w

script = 'perlscript.pl'
exec("/usr/bin/perl #{script}")

perlscript.pl

#!/usr/bin/perl -w
use strict;
print "Please enter your name: ";
my $name = <STDIN>;
chop($name);
if ($name eq "")
{
    print "You did not enter a name!\n";
    exit(1);
} else {
    print "Hello there, " . $name . "\n";
    exit(0);
}


perldoc perlipc states:

DESCRIPTION
       The basic IPC facilities of Perl are built out of the good old Unix
       signals, named pipes, pipe opens, the Berkeley socket routines, and
       SysV IPC calls.  Each is used in slightly different situations.

Ruby is capable of operating each of these.


Here's how ruby can use a python script, interacting with the script's stdin and stdout.

foo.py reads two integers (each on its own line) from standard input, adds them, and writes the result to standard-out. I don't know perl, so be nice to me:

#!/usr/bin/perl

$a = <STDIN>;
$b = <STDIN>;
$c = int($a) + int($b);
print $c;

foo.rb executes foo.py, giving it two numbers to add, getting back the result and printing it:

#!/usr/bin/ruby1.8

a = 1
b = 2
c = IO.popen('./foo.py', 'w+') do |pipe|
  pipe.puts(a)
  pipe.puts(b)
  pipe.close_write
  pipe.read
end
raise "foo.py failed" unless $? != 0
print "#{a} + #{b} = #{c}"    # => 1 + 2 = 3


What you want doesn't really exist, to my knowledge.

The closest thing to what you want, on a generic level, is XDebug. It turns a process into a little server that will accept debugging commands. This is generally used for debugging and profiling and not as interprocess communication, but its a possibility. I believe ActiveState's Perl can be run as an XDebug server.

Otherwise, you need explicitly program in some sort of side-channel that your Perl program listens to for commands (which is what XDebug does). It can be as simple as opening a socket that reads a string, evals it, encodes the result as YAML (or whatever) and writes it back. A REPL, but on a socket rather than on a terminal.

There are, obviously, security implications which will be left as an exercise for the reader. You also don't want listening to the socket to interrupt the program so you will now need something event-driven or threaded.

Sorry I don't have anything more specific. It would make a great CPAN module.


Perl and Ruby both have various "glues". Perl programs using the Expect module can do a lot more than just "wait for output". More likely though, you could communicate with a well-known protocol like HTTP... a Ruby daemon could put up a listener, and Perl could contact it, or vice versa.

But no, you can't just "embed" ruby code into Perl, or vice versa. You've got to run separate processes and communicate somehow.


Try Open4 . It is not designed specific for interacting with perl but with any program that need input and ouput. I am still learning to use it ,but I feel it might suit your need.


You mentioned in one of your comments that you want to run Perl code inside Ruby. This will not work unless you can make the Ruby interpreter understand Perl syntax. Can I get a BNF/yacc/RE for the Perl language? will help you understand the challenges you will face.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜