http://qs321.pair.com?node_id=134632

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

Can anyone please tell me how to run a C program within a perl script. I am getting frustrated and cannot figure this out.

peace, LOVE and ((code))

basicdez

Replies are listed 'Best First'.
Re: Running a C Program within Perl.
by Sniper (Scribe) on Dec 27, 2001 at 20:56 UTC
    You could use Inline.pm by Brian "Ingy" Ingerson

    examples : http://www.perl.com/pub/a/2001/02/inline.html
    module : http://www.cpan.org/modules/by-module/Inline/

    use Inline C => <<'END_C'; void greet() { printf("Hello, world\n"); } END_C greet;

    Simply run this script from the command line and it will print (you guessed it):

    Hello, world

    David "Sniper" Rigaudiere

      I am trying to run an external C program. I can run it fine from any Unix prompt, but when I put it into a perl program I get a long winded error, ending with "Directory" is not an identifier. Please help me I am very distraught.
        Please, post a piece of code :-)

        David "Sniper" Rigaudiere

Re: Running a C Program within Perl.
by vek (Prior) on Dec 27, 2001 at 20:56 UTC
    Basically, there are three ways to run an external prog - 1 - system. 2 - backticks. 3 - open a pipe.

    system:
    my $cmdToRun = "/path-to/the-c-prog"; system ($cmdToRun) && die "system $cmdToRun - $!\n";
    'system' just returns 0 on success and 1 on failure therefore you should test for it.

    backticks:
    my $cmdToRun = "/path-to/the-c-prog"; my @results = `$cmdToRun`;
    Using backticks is useful if you need to capture output from the program you are calling.

    pipe:
    my $cmdToRun = "/path-to/the-c-prog"; open (CMD, "$cmdToRun |") || die "open $cmdToRun - $!\n"; while (<CMD>) { # loop through the program output here... }
    UPDATE Of course this assumes you meant calling an external c prog from within perl. After reading sniper's post I realize you could have meant running actual c code from within perl - in that case Inline.pm would be the natural choice.
Re: Running a C Program within Perl.
by dmmiller2k (Chaplain) on Dec 27, 2001 at 20:59 UTC

    It's not clear which of two things you are asking

    • How to run an arbitrary external command line, which may or may not be the binary executable produced by compiling a C program.
    • How to call C code (say, as a subroutine call) directly from perl.
    The answer to the first question is simple and threefold:
    1. Run the command with back-ticks, assigning its STDOUT to a variable: as in, my $result = `commandline`;
    2. Use the system() function: as in, my $rc = system("commandline > result.log");
    3. Open the command as a pipe (if, say, you expect lots of output):
      # note vertical bar (pipe) at end of command open PH, "commandline|" or die "commandline: $!"; while (<PH>) { # ... do something with each line of output } close PH or die "commandline: $!";

    The answer to the second question is too involved to cover adequately here, but has been covered in depth elsewhere, among which are this and this.

    Update: Another option, as posited by Sniper, is of course to use Inline.pm, but once again, that's a whole 'nother ball of wax.

    dmm

    You can give a man a fish and feed him for a day ...
    Or, you can
    teach him to fish and feed him for a lifetime
Re: Running a C Program within Perl.
by dmmiller2k (Chaplain) on Dec 27, 2001 at 22:15 UTC

    (I have made this a reply to your original post; to continue the original thread would have indented too far for my taste)

    I can run this at the prompt, but putting in the following, /opt/BIPSConnect/bin/rdes, but when I put it in perl code (here is what I am trying to do - Quite simple and nothing complex, until I get this working) ...
    #!/usr/bin/perl-Tw use strict; my $cmd_to_run = "/opt/BIPSConnect/bin/rdes"; my @results = `$cmd_to_run`;
    I get the following error... /opt/BIPSConnect/bin/rdes: LD_LIBRARY_PATH=:/usr/lib:/usr/ucblib:/usr/openwin/lib:/usr/dt/lib:/usr/local/lib:/opt/hpnpl/lib:/p01cfg01/harvest/Harvest/lib:/opt/BIPSConnect/bin: is not an identifier

    Okay, this is obviously a UNIX (not DOS/Windows) platform, so that eliminates an entire subspecies of problems.

    I notice you are running your perl script with taint mode (-T). Are you, by chance, running it setuid, as well? In setuid mode Solaris (under which you appear to be running) closes the executable file and reopens it such that the program sees /dev/fd4 (or fd5, ...) instead of the name of the actual executable as $0, among other things. In taint mode Perl's behavior apropos the environment is somewhat different as well; certain specific variables must be set to known "safe" values (PATH and LD_LIBRARY_PATH come to mind, for example). Take a look at Perl security for more on this topic.

    Update: Is it possible that the message you're seeing has something to do with trying to use the Bourne shell syntax,

    [ENVVAR=value ...] command

    with csh or tcsh, which do not permit this? What is your default shell?

    Just asking ...

    dmm

      Here is what rdes looks like.
      export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/BIPSConnect/bin /opt/BIPSConnect/bin/micn_cr2k_bips_test_console /home/w951an6/perl/ph +ase_II/xxx.xml
      does that help in knowing how to execute it?
        export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/BIPSConnect/bin /opt/BIPSConnect/bin/micn_cr2k_bips_test_console /home/w951an6/perl/ph +ase_II/xxx.xml

        If that's the whole script, then you are missing the shebang line, i.e., #!/bin/sh, without which, Perl will attempt to execute it with your default shell, which (you didn't say) might be of the csh variety, not a Bourne-style (sh-like) shell.

        Try putting a shebang as the first line.

        dmm

I got it working now.
by basicdez (Pilgrim) on Dec 28, 2001 at 01:22 UTC

    Thanks to dmmiller2k and all of the others who helped me with this. The problem was that perl was looking for a bourne shell program and I was trying to run a korne shelle script. Once again, I will NOT make that mistake ever again. I feel both knowledgable and empowered. Thanks perl monks....

    Happy new Year to everyone.

      You're quite welcome.

      Lesson for the day: never field a shell script without a shebang line!

      dmm

      You can give a man a fish and feed him for a day ...
      Or, you can
      teach him to fish and feed him for a lifetime
      For the record, I think a lot of difficulty figuring out this problem stemmed from the fact that you kept referring to the target as a "C program" when it was in fact a shell script.
Re: Running a C Program within Perl.
by hotshot (Prior) on Dec 27, 2001 at 20:30 UTC
    You should run your C program as system call within your perl code:
    system('/tmp/example.c'); # or `/tmp/example.c` # back ticks


    Hotshot

      You probably don't mean to execute the actual .c file itself ... if memory serves, you'd probably want to run /tmp/example or /tmp/a.out (under UNIX) or /tmp/example.exe (under Windows/DOS).

      dmm

        You are correct, but how do I do that?