从C程序执行php脚本并将结果存储到变量中

我想从C程序执行PHP脚本并将返回的内容存储到C变量中。

我试过跟随,但它不起作用:

C:

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

PHP:

  

环境:

  • PHP 5.2.6
  • Apache 2.0
  • Fedora Core 10

还建议任何其他更好的方法来做到这一点。

这里简短的回答是使用system()popen()而不是execl() 。 看到Jason已经发布了一个关于使用popen()的好答案,我将跳过它并解释如何使用execl()以防万一你真正关心。 最有可能的是,这是所有不必要的技术性的巨型 – 但是该死的,在讨论popen()之前,我已经将其中的大部分内容作为一个很长的前奏,我现在不会丢掉它!

首先…

调用execl()所有命令行参数都需要单独传递。 此外,第一个参数必须重复,因为任何程序的main() argv[0]传统上都是程序的名称。 所以固定电话应该是这样的:

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

(我将转换添加到(char *)以确保将空指针作为最终参数而不是整数0传递,如果NULL恰好定义为0而不是(void *) 0 ,这是合法的。)

然而…

这会使execl()调用正确,但是存在更大的问题。 exec系列函数几乎总是与fork()和一些复杂的pipe()杂耍一起使用。 这是因为exec函数不在单独的进程中运行程序; 他们实际上取代了当前的流程! 所以一旦你调用execl() ,你的代码就完成了。 成品。 execl()永远不会返回。 如果你只是像你所做的那样调用它,你将永远不会看到会发生什么,因为你的程序将神奇地转换为/usr/bin/php进程。

好的,那么fork()pipe()含义是什么? 在高层次上,您需要做的是将流程分为两个流程。 父进程将继续是“你的”进程,而子进程将立即调用execl()并将其自身转换为/usr/bin/php 。 然后,如果您已将父进程和子进程正确连接在一起,则它们将能够相互通信。

长话短说,如果你还在这里并且没有点头,你应该向智慧的oracle谷歌咨询有关所有这些的更多细节。 有很多网站提供更多关于如何进行fork / exec舞蹈的(!)深入细节。

我不会离开你的。 这是我用于我自己的程序的函数,它完全符合我的概述。 它实际上与popen()非常相似,唯一的区别是调用者除了stdinstdout之外还可以访问子stderrstderr流。

码…

 #include  #include  #include  #include  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; } } 

可能最简单的方法是使用popen函数 :(摘自链接页面):

以下示例演示如何使用popen()和pclose()执行命令ls *以获取当前目录中的文件列表:

 #include  ... 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() */ ... } 

但是,想要从C程序中读取PHP脚本的输出是一种危险信号,我怀疑可能有一些更清晰的整体解决方案,但如果没有更高级别的描述,你很难说更多重新尝试做。

请记住,当您使用execl() ,它将“成功退出”。 所以,你永远不会看到“结束PHPfunction”,因为它永远不会到达那行代码。

要解决此问题,您可以使用system或使用fork()创建子进程,并在子进程中使用execexec系列中的任何其他函数。