tags:

views:

348

answers:

9

It's my understanding that there's no "bridge" between Ruby and Perl to let you 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.

+2  A: 

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.

Randal Schwartz
I understand that there needs to be glue - but is there software built to handle this? I wouldn't mind using an inter-process mediator, so long as it was written well. (Also, I'd like to forgo writing one if possible.)
Mike
Inline::Ruby allows running Ruby code inside Perl program. And it allows calling Perl subs too, so it is possible to use Ruby as main language.
Alexandr Ciornii
You can embed perl into Ruby as well as any other C program. Not that you should want to, but perl is designed to allow that. Going the other way, Perl has the Inline modules.
brian d foy
+3  A: 

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.

mobrule
This is the opposite of what I want to do - I want to run Perl code inside of Ruby.
Mike
Mike: Inline:: modules usually allow callbacks to Perl code. So you can run your Ruby program from small Perl program.
Alexandr Ciornii
+2  A: 

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.

pierr
Hmm, this answers my first question, but I'd still be very nervous about interacting via stdin/stdout.
Mike
+1  A: 

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
Wayne Conrad
A: 

If you're writing both the Perl and the Ruby programs, then there shouldn't be any problem.

If you're only writing one and not the other, tell us which, and explain what the problem actually is.

AmbroseChapel
+2  A: 

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.

Schwern
+3  A: 

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.

fennec
A: 

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.

David Harris
You don't need the Ruby interpreter to understand Perl. You just (just!) need to embed Perl in a C extension for Ruby. :)
brian d foy
A: 

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);
}