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

Dear Monks, If I have a C program like this:

int main() { return 5; }
Is there a way to get the value 5 from that C program?

I know I can do a printf (or cout) and capture the standard out in the perl script, but is there a way to in-line a C function/program and get the return value?

I thought it might be useful in some applications.

The main reason I am asking this is to get the output from the C function gettimeofday so that I can get the time at micro second granularity.

Thanks

Replies are listed 'Best First'.
Re: getting the return value from a C program
by Limbic~Region (Chancellor) on Mar 22, 2004 at 17:39 UTC
    podian,
    You are going to want to take a look at least two things: The first one allows you to in-line C code. The second will allow you to capture the output of an externally called C program as in:
    my $foo = qx{ ./external };
    Cheers - L~R
      perldoc -f qx

      Um, the OP was asking about capturing the exit status of a C program, which involves using the "system()" call (perldoc -f system) -- not "qx" (aka the backtick operator), which just captures the program's stdout. Also -- OOPS, sorry. I should have read the docs more carefully myself, to see that qx returns stdout and sets $? -- thanks, I'm glad I finally learned that. Anyway (end of update), the more direct reference for qx is "perldoc perlop" (which is where "perldoc -f qx" tells you to look).

      Another reply below points to the usage of "system()", along with the "$?" variable -- though I prefer using a scalar that has a meaningful name, e.g.:

      my $exit_stat = system( "some_shell_command ..." ); printf "Shell_command exit status was %d\n", $exit_stat/256; print "(which means it probably failed)\n" if $exit_stat != 0;
      (closing remark to updates: my old habit of using "system()" to get the exit status, vs. using backticks to get stdout data, was simply a matter of being unaware of the $? variable, which is set in either case.)
Re: getting the return value from a C program
by waswas-fng (Curate) on Mar 22, 2004 at 17:43 UTC
    In addition to what L~R said, use Time::HiRes if you want to get micro second granularity...


    -Waswas
Re: getting the return value from a C program
by matija (Priest) on Mar 22, 2004 at 17:45 UTC
    Is there a way to get the value 5 from that C program?
    Yes, examine the value of $? after system (or backticks) has returned.

    I know I can do a printf (or cout) and capture the standard out in the perl script, but is there a way to in-line a C function/program and get the return value?
    Sure! You could do an XS interface, or use Inline::C.

    The main reason I am asking this is to get the output from the C function gettimeofday so that I can get the time at micro second granularity.
    Oh!No need to complicate then: just use Time::HiRes, and it will make gettimeofday available to you as a function.

Re: getting the return value from a C program
by calin (Deacon) on Mar 22, 2004 at 18:24 UTC

    The return value of main() in a standalone C program is used as an error or status indication code and should not be used for other purposes. Normally programs should return 0. Its range is also limited: 0-255 (?) integer on most (UNIX) systems.

    If that's what you really want (I doubt), here's how you can get to it (tested on Linux) (see perldoc perlvar for documentation on $?)

    $ cd /tmp $ cat > ret5.c int main(int argc, char **argv) { return 5; } ^D $ gcc ret5.c -o ret5 $ perl system './ret5'; printf "child return code is: %d\n", $? >> 8; ^D child return code is: 5 $

Re: getting the return value from a C program
by zentara (Cardinal) on Mar 23, 2004 at 15:53 UTC
    You will probably find IPC::Open3 useful, you can talk and listen to the c program.
    #!/usr/bin/perl use warnings; use strict; use IPC::Open3; #interface to "bc" calculator #my $pid = open3(\*WRITE, \*READ, \*ERROR,"bc"); my $pid = open3(\*WRITE, \*READ,0,"bc"); #if \*ERROR is false, STDERR is sent to STDOUT while(1){ print "Enter expression for bc, i.e. 2 + 2\n"; chomp(my $query = <STDIN>); #send query to bc print WRITE "$query\n"; select(undef,undef,undef,2); #get the answer from bc chomp(my $answer = <READ>); print "$query = $answer\n"; } waitpid($pid, 1); # It is important to waitpid on your child process, # otherwise zombies could be created.

    I'm not really a human, but I play one on earth. flash japh