Frage

Ich mag einen PHP-Skript aus einem C-Programm ausführen und speichern Sie die wiederkehrenden Inhalte in ein C-Variable.

Ich habe versucht, wie folgt, aber es funktioniert nicht:

C:

printf("calling php function\n");
execl("/usr/bin/php -q", "/var/www/html/phpinfo.php", NULL);
printf("End php function\n");

PHP:

<?php
echo "hello";
?>

Umwelt:

  • PHP 5.2.6
  • Apache 2.0
  • Fedora Core 10

Auch deuten darauf hin, andere besseren Weg, dies zu tun.

War es hilfreich?

Lösung

hier Kurze Antwort ist system() oder popen() zu verwenden, anstatt execl(). Da Jason hat bereits gebucht eine gute Antwort über popen() verwenden, werde ich das und erklären überspringen, wie execl() verwenden nur, wenn Sie wirklich interessieren. Höchstwahrscheinlich ist das alles unnötige technische Hokuspokus - aber verdammt noch mal, ich habe die meisten dieser getippt bereits als lange Vorspiel vor popen() diskutieren und ich warf es jetzt nicht weg

Zum einen ...

Wenn müssen alle Befehlszeilenargumente Aufruf execl() separat übergeben werden. Außerdem muss das erste Argument wiederholt werden, wie argv[0] in jedem main() Programm ist traditionell der Name des Programms. So sollte die feste Anruf wie folgt aussehen:

execl("/usr/bin/php", "/usr/bin/php", "-q",
    "/var/www/html/phpinfo.php", (char *) NULL);

(I hinzugefügt, um die Besetzung (char *) um sicherzustellen, dass ein Nullzeiger als das letzte Argument übergeben wird, anstatt die ganze Zahl 0, wenn NULL geschieht als 0 definiert werden und nicht (void *) 0, was legal ist.)

Jedoch ...

Dies wird die execl() Anruf richtig, aber es gibt ein größeres Problem. Die exec Familie von Funktionen sind fast immer in Kombination mit fork() und einigen komplizierten pipe() Jonglieren verwendet. Dies liegt daran, die exec Funktionen das Programm nicht in einem separaten Prozess ausgeführt; sie ersetzen tatsächlich den aktuellen Prozess! Also, wenn Sie rufen execl(), ist Ihr Code. Fertig. execl() nie zurückgibt. Wenn Sie es nur nennen, wie du getan hast, du wirst nie zu sehen bekommen, was passiert, wenn Ihr Programm auf magische Weise in einen /usr/bin/php Prozess verwandeln.

OK, so was ist das über fork() und pipe()? Auf einem hohen Niveau, was Sie zu tun haben, ist Ihr Prozess in zwei Prozesse aufgeteilt. Der übergeordnete Prozess wird fortgesetzt, „Ihr“ Prozess, während das Kind Prozess sofort execl() anrufen und verwandelt sich in /usr/bin/php. Dann, wenn Sie die Eltern-Kind-Prozesse verdrahtet haben richtig zusammen werden sie miteinander kommunizieren können.

Um eine lange Geschichte kurz zu machen, wenn Sie noch hier sind und nicht einnickte sollten Sie die klugen Orakel Google für viel mehr Details über all dies konsultieren. Es gibt viele Web-Sites gibt gibt noch mehr (!) In ausführlichen Details darüber, wie die fork / exec Tanz zu tun.

Ich werde dich nicht verlassen, obwohl hängen. Hier ist eine Funktion, die ich für meine eigene Programme verwenden, das tut genau das, was ich skizziert habe. Es ist sehr ähnlich in der Tat popen(), der einzige Unterschied ist, dass der Anrufer die stderr Strom zusätzlich Kind zugreifen können, um stdin und stdout.

-Code ...

#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

pid_t execute(const char *command, FILE **in, FILE **out, FILE **err)
{
    pid_t pid;
    int   fd[6];

    pipe(&fd[0]);
    pipe(&fd[2]);
    pipe(&fd[4]);

    switch (pid = fork()) {
        case -1:
            perror("unable to fork()");
            exit(1);

        case 0:
            close(fd[1]);   // Close write end of stdin.
            close(fd[2]);   // Close read end of stdout.
            close(fd[4]);   // Close read end of stderr.

            dup2(fd[0], STDIN_FILENO);  // Have stdin read from the first pipe.
            dup2(fd[3], STDOUT_FILENO); // Have stdout write to the second pipe.
            dup2(fd[5], STDERR_FILENO); // Have stderr write to the third pipe.

            execlp("/bin/sh", "/bin/sh", "-c", command, (char *) NULL);

            perror("execlp() failed");
            _exit(1);

        default:
            close(fd[0]); // Close read end of stdin.
            close(fd[3]); // Close write end of stdout.
            close(fd[5]); // Close write end of stderr.

            if (in)  *in  = fdopen(fd[1], "wb"); else close(fd[1]);
            if (out) *out = fdopen(fd[2], "rb"); else close(fd[2]);
            if (err) *err = fdopen(fd[4], "rb"); else close(fd[4]);

            return pid;
    }
}
scroll top