Hello,
I have a C program that builds and runs fine on my Fedora 11 box. This program uses popen as follows:
FILE *pipe = popen("perl - ", "w"); if(pipe) { int i = 0;
// Send a Perl script to the STDIN of 'pipe'. for( ; i< sizeof(perlScript) / sizeof(perlScript[0]); ++i) { fprintf(pipe, "%c", perlScript[i]); }
pclose(pipe); }
I would like to know if MinGW can help me: 1. cross-compile the above C program (on my Fedora 11 for the Windows platform), 2. without having to replace the above call to popen by less than ideal Windows counterparts like _popen (which pops up an ugly CMD console window!), or CreatePipe, or CreateNamedPipe, etc.
Regards, /HS
Op zaterdag 19-09-2009 om 11:30 uur [tijdzone +0530], schreef Harry Simons:
Hello,
I have a C program that builds and runs fine on my Fedora 11 box. This program uses popen as follows:
FILE *pipe = popen("perl - ", "w"); if(pipe) { int i = 0; // Send a Perl script to the STDIN of 'pipe'. for( ; i< sizeof(perlScript) / sizeof(perlScript[0]); ++i) { fprintf(pipe, "%c", perlScript[i]); } pclose(pipe); }
I would like to know if MinGW can help me:
- cross-compile the above C program (on my Fedora 11 for the Windows platform),
- without having to replace the above call to popen by less than ideal Windows counterparts like _popen (which pops up an ugly CMD console window!), or CreatePipe, or CreateNamedPipe, etc.
Regards, /HS
Hi Harry,
For one of my own projects I've used this piece of code as a replacement for popen on Win32. It uses the Win32 API functions CreatePipe and CreateProcess and it doesn't show an ugly CMD console window:
-------
#ifdef WIN32 #include <windows.h> #include <io.h>
#define popen pt_popen #define pclose pt_pclose
HANDLE my_pipein[2], my_pipeout[2], my_pipeerr[2]; char my_popenmode = ' ';
static int my_pipe(HANDLE *readwrite) { SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa); sa.bInheritHandle = 1; sa.lpSecurityDescriptor = NULL;
if (!CreatePipe (&readwrite[0],&readwrite[1],&sa,1 << 13)) { errno = EMFILE; return -1; }
return 0; }
static FILE * pt_popen(const char *cmd, const char *mode) { FILE *fptr = (FILE *)0; PROCESS_INFORMATION piProcInfo; STARTUPINFO siStartInfo; int success, catch_stderr;
my_pipein[0] = INVALID_HANDLE_VALUE; my_pipein[1] = INVALID_HANDLE_VALUE; my_pipeout[0] = INVALID_HANDLE_VALUE; my_pipeout[1] = INVALID_HANDLE_VALUE; my_pipeerr[0] = INVALID_HANDLE_VALUE; my_pipeerr[1] = INVALID_HANDLE_VALUE;
if (!mode || !*mode) goto finito;
my_popenmode = *mode; if (my_popenmode != 'r' && my_popenmode != 'w') goto finito;
catch_stderr = strstr((char *) cmd, "2>&1") != NULL; if (catch_stderr) { char *ptr = strstr((char*) cmd, "2>&1"); *ptr = '\0'; }
if (my_pipe(my_pipein) == -1 || my_pipe(my_pipeout) == -1) goto finito; if (!catch_stderr && my_pipe(my_pipeerr) == -1) goto finito;
ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); siStartInfo.cb = sizeof(STARTUPINFO); siStartInfo.hStdInput = my_pipein[0]; siStartInfo.hStdOutput = my_pipeout[1]; if (catch_stderr) siStartInfo.hStdError = my_pipeout[1]; else siStartInfo.hStdError = my_pipeerr[1]; siStartInfo.dwFlags = STARTF_USESTDHANDLES;
success = CreateProcess(NULL, (LPTSTR)cmd, // command line NULL, // process security attributes NULL, // primary thread security attributes TRUE, // handles are inherited DETACHED_PROCESS, // creation flags NULL, // use parent's environment NULL, // use parent's current directory &siStartInfo, // STARTUPINFO pointer &piProcInfo); // receives PROCESS_INFORMATION
if (!success) goto finito;
CloseHandle(my_pipein[0]); my_pipein[0] = INVALID_HANDLE_VALUE; CloseHandle(my_pipeout[1]); my_pipeout[1] = INVALID_HANDLE_VALUE; CloseHandle(my_pipeerr[1]); my_pipeerr[1] = INVALID_HANDLE_VALUE;
if (my_popenmode == 'r') fptr = _fdopen(_open_osfhandle((long)my_pipeout[0],_O_BINARY),"r"); else fptr = _fdopen(_open_osfhandle((long)my_pipein[1],_O_BINARY),"w");
finito: if (!fptr) { if (my_pipein[0] != INVALID_HANDLE_VALUE) CloseHandle(my_pipein[0]); if (my_pipein[1] != INVALID_HANDLE_VALUE) CloseHandle(my_pipein[1]); if (my_pipeout[0] != INVALID_HANDLE_VALUE) CloseHandle(my_pipeout[0]); if (my_pipeout[1] != INVALID_HANDLE_VALUE) CloseHandle(my_pipeout[1]); if (my_pipeerr[0] != INVALID_HANDLE_VALUE) CloseHandle(my_pipeerr[0]); if (my_pipeerr[1] != INVALID_HANDLE_VALUE) CloseHandle(my_pipeerr[1]); }
return fptr; }
static int pt_pclose(FILE *file) { if (!file) { return -1; }
fclose(file);
CloseHandle(my_pipeerr[0]); if (my_popenmode == 'r') CloseHandle(my_pipein[1]); else CloseHandle(my_pipeout[0]);
return 0; } #endif
----
Note that this piece of code only supports one open file descriptor at the same time (because of the global variables which are used). It may need some further adjustment to fit in your particular case.
Regards,
Erik van Pienbroek
On Sat, Sep 19, 2009 at 11:30:59AM +0530, Harry Simons wrote:
Hello,
I have a C program that builds and runs fine on my Fedora 11 box. This program uses popen as follows:
FILE *pipe = popen("perl - ", "w");
[...]
I would like to know if MinGW can help me:
- cross-compile the above C program (on my Fedora 11 for the Windows platform),
Yes, but ..
- without having to replace the above call to popen by less than ideal Windows counterparts like _popen (which pops up an ugly CMD console window!), or CreatePipe, or CreateNamedPipe, etc.
No.
You have to program against the Win32 API. There's no POSIX translation layer in MinGW.
Having said that, there are some things which can help:
(a) Use a higher-level portable API, eg. glib, APR, NSPR ... I'm sure one of these has a replacement for popen functionality. These libraries often help you port to other platforms too, so it can be useful to modify your code to use them.
(b) Use the replacement functions from Gnulib. Sadly Gnulib doesn't have a popen replacement yet, but it does have replacements for many other POSIX and libc functions.
http://www.gnu.org/software/gnulib/manual/gnulib.html
(c) Look at MSDN's example using pipes. The Win32 API is horrible, but it's still possible to use pipes and redirect, although nowhere near as elegant and simple as in POSIX:
http://stackoverflow.com/questions/450865/what-is-the-equivalent-to-posix-po...
Rich.