Proc_open() C++/Python

0 投票
3 回答
2642 浏览
提问于 2025-04-16 06:19

我正在尝试用proc_open来调用一个C++或Python文件(需要双向支持)。

经过一些网上搜索,我写了这段代码:(我最开始用C++试了,失败后又试了Python)

PHP:

<?php
$descriptorspec = array(
   0 => array("pipe", "r"),
   1 => array("pipe", "w"),
   2 => array("file", "error-output.txt", "a")
);

$process = proc_open('new.exe', $descriptorspec, $pipes);

$input = 20;
$exp = 2;
if (is_resource($process)) {
    print fgets($pipes[1]);
    fwrite($pipes[0], $input);

    print fgets($pipes[1]);
    fwrite($pipes[0], $exp);

    print fgets($pipes[1]);

    fclose($pipes[1]);
    fclose($pipes[0]);
    $return_value = proc_close($process);

    echo "command returned $return_value\n";
} else {
    echo "No resource availeble";
}
?>

C++:

#include <iostream>
using namespace std;

int main () {
    // Get variables from php
    cout << "input" << endl;
    cin << input
    cout << "exponent" << endl;
    cin << exp

    // Process variables
    int answer = input + exp;

    // Return variables
    cout << answer;

    // End c++ script
    return 0;
}

Python:

print 'enter input'
inp = raw_input()

print 'enter exponent'
exp = raw_input()

ant = inp + exp

print ant

但是很遗憾,我一直遇到同样的错误:文件未被识别为内部或外部命令、程序或批处理文件。

一些额外的信息:

我使用的是Wamp,PHP版本是5.3.0。我从proc_close()得到的返回值是1。

3 个回答

0

指定可执行文件的绝对路径:

$process = proc_open('/path/to/new.exe', $descriptorspec, $pipes);

我可以通过命令行调用下面的PHP脚本,让PHP和Perl进行交流,使用的是proc_open:

#!/usr/bin/php -q
$descriptorspec = array(
   0 => array("pipe", "r"),
   1 => array("pipe", "w"),
   2 => array("file", "error.log", "a")
);

$process = proc_open('/path/to/procopen.pl ' . $argv[1],
    $descriptorspec, $pipes);

if (is_resource($process)) {

  // print pipe output
  echo stream_get_contents($pipes[1]);

  // close pipe
  fclose($pipes[1]);

  // close process
  proc_close($process);
}

这是我的Perl脚本,它和上面的PHP脚本在同一个目录下:

#!/usr/bin/perl
print @ARGV;

但是我在调用你的Python脚本时,PHP却无法运行。命令行一直卡在那里,为什么会这样呢?

0

你可能误解了 proc_open() 的作用。它的功能就像你在命令行中打开一个进程,比如在 Unix 系统中输入 diff file1.txt file2.txtproc_open() 并不是用来直接运行一个可执行文件的。

根据我认为你参考的页面,http://php.net/manual/en/function.proc-open.php,如果你想执行一个外部程序,应该使用 exec()。你可以这样使用它(前提是可执行文件在正确的目录下):

<?php
echo exec('someprogram.exe');
?>

注意:我不确定这是否适用于 Windows 的可执行文件。

这里假设 someprogram.exe 是从你提供的 C++ 源代码编译而来的可执行文件。如果你想从 PHP 运行一个 Python 程序,首先祝你在 Windows 上好运,不过你应该使用 proc_open() 来调用 python somescript.py,就像你在命令行中那样操作。

2

你的代码里有两个问题(至少在运行你的Python脚本时会出现问题)。首先,你没有把Python的输出及时发送到标准输出(STDOUT),所以这些输出根本到不了PHP。这就导致了fgetc()一直在等待,无法继续执行。解决这个问题很简单,只需要在代码里加上几行flush()

#!/usr/bin/env python
import sys

print 'enter input'
sys.stdout.flush()
inp = raw_input()

print 'enter exponent'
sys.stdout.flush()
exp = raw_input()

ant = inp + exp

print ant
sys.stdout.flush()

然后,在你的PHP代码中,当你向Python脚本的标准输入(STDIN)写入数据时,没有发送换行符。所以,Python的raw_input()会一直等待换行符,导致程序卡住。这个问题也很容易解决。只需在fwrite()的调用中添加"\n"即可:

#!/usr/bin/php
<?php
$descriptorspec = array(
   0 => array("pipe", "r"),
   1 => array("pipe", "w"),
   2 => array("file", "error-output.txt", "a")
);

$process = proc_open('/path/to/python/script.py', $descriptorspec, $pipes);

$input = 20;
$exp = 2;
if (is_resource($process)) {
    print fgets($pipes[1]);
    fwrite($pipes[0], $input . "\n");

    print fgets($pipes[1]);
    fwrite($pipes[0], $exp . "\n");

    print fgets($pipes[1]);

    fclose($pipes[1]);
    fclose($pipes[0]);
    $return_value = proc_close($process);

    echo "command returned $return_value\n";
} else {
    echo "No resource availeble";
}

只要做了这些修改,我就能让你的代码按预期工作:

$ ./procopen.php 
enter input
enter exponent
202
command returned 0

撰写回答