n4nature has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I want to run a C program from within Perl program and redirect its output in a file, that the perl program can read later on. I tried backquotes to run sample C program (hello.exe) from Perl, but it gives error saying "hello.exe is not an internal or external command. Here's the program:
#!/usr/bin/perl use Test::More; use Test::Deep; my $o_file = "output.txt"; my $bin = 'hello.exe'; # run the C program $result = `$bin > output.txt`; print $result;

Replies are listed 'Best First'.
Re: Running a C program from Perl
by ikegami (Patriarch) on May 25, 2009 at 19:04 UTC
    hello.exe isn't in the current directory or in the PATH. Specify the full path to the program.
Re: Running a C program from Perl
by jettero (Monsignor) on May 25, 2009 at 21:43 UTC
    Fix what ikegami says. You might also consider handling the redirection yourself. It doesn't make much difference if the shell does it or if perl does it, but from perl, it might just be more readable (or at least more pliable). You could also possibly alter the output on the way through:
    use strict; # consider this also use warnings; # consider this also open my $input, "-|", "./hello.exe" or die "woops: $!"; open my $output, ">", "output.txt" or die "darn: $!"; while(my $line = <$input>) { # optionally do things here print $output $line }

    (autodie seems to be more fashionable than my or dies too.)

    In any case, doing the above would have complained more perlishly (perhaps) than the shell. It'd be more reliable if you could use the list version of the open popen. If it won't hurt anything it might even help to call it like this: open my $input, "-|", qw(./hello.exe 1) or die "popen fail: $!". If you can use the list version of open, you definitely get a perl error since the shell isn't even involved!

    -Paul

Re: Running a C program from Perl
by graff (Chancellor) on May 25, 2009 at 23:19 UTC
    Just to point out something odd about this line in the OP code:
    $result = `$bin > output.txt`;
    The backticks around the command-line string tell perl to capture whatever output is produced on the command's stdout, but since the command includes a redirection of stdout to a file, there will be nothing available for perl to assign to your "$result" variable -- it will get an empty string, because all the stdout content from "hello.txt" is written (via redirection) to the "output.txt" file.

    I get the impression that this isn't what you intended. If you want $result to store the (numeric) exit status of the command, use system; if you want it to get the stdout content from the command, remove the  > output.txt part from the command line string.

      I was wondering why $result was empty. Thanks! If I want to read and analyze results in Perl from a file (output.txt generated by C++ program), what's the command/module for that? Thanks.
      By way of pedantry, when you say ...nothing available for perl to assign..., isn't quite right since $result can be non-empty i.e. iff $bin generates anything to STDERR ... either by accident or design :D

      A user level that continues to overstate my experience :-))
        $result can be non-empty i.e. iff $bin generates anything to STDERR .

        If the command in backticks generates any output on its own stderr, that goes directly to the perl script's STDERR, and does not get captured/assigned by the backticks -- in the OP case, $result will still be empty, because backticks only return what went to the command's stdout.

        Now, if the command being run in backticks included redirection of stderr to stdout (and no subsequent redirection of stdout to some file), then backticks would capture any stderr content along with any stdout -- e.g. if your backticks are executing a bourne-style shell, the following would generally include some sort of error message to the perl variable, along with any matching lines found by grep in ~/.bashrc:

        my $result = `grep PATH ~/.bashrc /no/such/file 2>&1`