PHP-Skript aus C-Programm ausführt und die Ergebnisse in einer Variablen
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.
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;
}
}
Andere Tipps
Wahrscheinlich wäre der einfachste Weg, um die rel="noreferrer">: (Auszug aus verlinkten Seite):
Das folgende Beispiel zeigt die Verwendung von popen () und pclose () den Befehl ls * auszuführen, um eine Liste der Dateien im aktuellen Verzeichnis zu erhalten:
#include <stdio.h>
...
FILE *fp;
int status;
char path[PATH_MAX];
fp = popen("ls *", "r");
if (fp == NULL)
/* Handle error */;
while (fgets(path, PATH_MAX, fp) != NULL)
printf("%s", path);
status = pclose(fp);
if (status == -1) {
/* Error reported by pclose() */
...
} else {
/* Use macros described under wait() to inspect `status' in order
to determine success/failure of command executed by popen() */
...
}
Doch aus einem C-Programm die Ausgabe eines PHP-Skript lesen will, ist eine Art roter Fahne, und ich vermute, es ist wahrscheinlich etwas sauberen Gesamt Lösung dieses Problem, aber es ist schwer, mehr zu sagen, ohne eine höhere Ebene Beschreibung was Sie versuchen zu tun.
Denken Sie daran, wenn Sie execl()
verwenden, es wird „exit auf Erfolg“. Also, werden Sie nie sehen „PHP-Funktion beenden“, weil es nie zu dieser Zeile Code erhalten wird.
Um dieses Problem zu überwinden, können Sie entweder system
verwenden oder fork()
verwenden, um ein Kind-Prozess zu erstellen und in Ihrem Kind Prozess Verwendung execl
oder jede andere Funktion aus der exec
Familie.