如何在C中调用外部程序,以便我可以写入stdin
并从stdout
读取?有很多像这样的问题,但似乎没有人完全回答它。比方说,我有一些程序,我想让其他程序做一些事情,比如这个伪代码:
int * myinput = "this is my input"
FILE ** io = external_program("otherprogram arg1 arg2");
char c;
fprintf(io[0],myinput); // Writes my input to the programs stdin
while((c = fgetc(io[1])) != EOF) {
printf("I just read %c from otherprogram!",c);
}
我无法找到它,我认为external_program
之类的内容可能不存在。我怎么能得到类似的东西,我有一个程序在外部使用filedescriptors运行stdin
,stdout
,如果可能的话stderr
?
这样我可以,例如,有一些程序用某种语言读取代码,将其编译为C或其他语言,并使用GCC来获取结果,而不必创建(并可能覆盖)文件,如这样:
FILE ** io = external_program("gcc -xc -");
FILE * output = open(output_file_path); // Program's own output
// ... generate C code, writing to io[0] ...
// Now write the output to our own output file
while((c = fgetc(io[1])) != EOF) {
fputs(output,c);
}
close (output);
答案 0 :(得分:1)
你需要两个管道,一个用于管道输入到孩子的stdin
另一个用于阅读它stdout
。在类似UNIX / Linux的环境中,创建子进程可能如下所示:
FILE **p2open( const char *cmd, FILE **fpbuf )
{
FILE **result;
int fd1[2], fd2[2];
int ispipe1 = ERROR, ispipe2 = ERROR;
pid_t cpid;
// open two pipes: Pipe1: parent reads, pipe2_: paretn writes
if( (ispipe1 = pipe( fd1 )) == -1 ||
(ispipe2 = pipe( fd2 )) == -1 )
{
return NULL;
}
switch( cpid = fork() ) {
case -1:
return NULL;
case 0: /* Child */
dup2( fd2[0], 0 );
dup2( fd1[1], 1 );
close( fd1[0] ); close( fd1[1] );
close( fd2[0] ); close( fd2[1] );
execlp( "/bin/sh", "sh", "-c", cmd, NULL );
break;
default: /* parent */
if( (fpbuf[0] = fdopen( fd1[0], "r" )) == NULL ||
(fpbuf[1] = fdopen( fd2[1], "w" )) == NULL )
{
result = NULL;
} else {
result = fpbuf;
}
}
if( ispipe1 != ERROR ) {
close( fd1[1] );
if( !result ) close( fd1[0] );
}
if( ispipe2 != ERROR ) {
close( fd2[0] );
if( !result ) close( fd2[1] );
}
return result;
}
您现在可以致电:
FILE *pipefp[2];
if( p2open( "mycmd", pipefp ) != NULL ) {
// now you have pipefp[0] for readinf pipefp[1] for writing
..
}
当然,您还应该实现匹配的p2close()
功能,但我认为您可以管理
这是一个适用于Linux和solaris的测试主程:
int main(int argc, char *argv[] )
{
FILE *fp[2];
int c;
if( p2open( "cat", fp ) != NULL ) {
fputs( "go!\n", fp[1] );
fclose( fp[1] );
while( (c = fgetc( fp[0] )) != EOF ) {
fputc( c, stdout );
}
}
}
答案 1 :(得分:0)
这超越了vanilla C并进入了进程间通信,这是特定于平台的(也就是说,Windows的答案可能与* nix的答案不同)。
这是一个使用管道的简单* nix示例(取自Steve和Kay Robbins现在的绝版“Practical Unix Programming”):
/**
* The following includes are specific to *nix
*/
#include <unistd.h>
#include <fcntl.h>
int main( int argc, char **argv )
{
int fd[2]; // file descriptors for pipe
pid_t childpid;
pipe( fd );
if ( (childpid = fork()) == 0 )
{
// this is the child process
dup2( fd[1], STDOUT_FILENO );
close( fd[0] );
close( fd[1] );
execl( "/bin/ls", "ls", "-l", argv[1], NULL );
perror( "The exec of ls failed" );
}
else
{
// this is the parent process
dup2( fd[0], STDIN_FILENO );
close( fd[0] );
close( fd[1] );
execl( "/usr/bin/sort", "sort", "-n", "+4", NULL );
perror( "The exec of sort failed" );
}
return 0;
}
这基本上是shell命令ls -l <path> | sort -n +4
的C实现。使用ls
描述符表和sort
命令将fd
的标准输出提供给pipe
的标准输入。
正如所写,这是一个单向沟通渠道,这是我所做过的一切。我没有一个好的双向示例。
答案 2 :(得分:-1)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main()
{
char ext_prog[]="prog name"; //your external program
char arguments[]="args > file.txt"; //arguments
strcat(ext_prog,arguments); //join the strings to ext_prog
system(ext_prog); //execute on shell
}
这会将输出保存到file.txt,您可以对其进行解析。
编辑:还有其他方法可以解决这个问题。这是最重要的。尝试使用popen()
和FILE
指针。