Popen Equivalent in C++

popen equivalent in c++

You can use the "not yet official" boost.process if you want an object-oriented approach for managing the subprocess.

Or you can just use popen itself, if you don't mind the C-ness of it all.

What is the equivalent to Posix popen() in the Win32 API?

MSDN explains how you do what popen does using the Windows API in Pipe Handle Inheritance . Here it provides a well-documented example. It's way more low-level than the _popen function found in the runtime library linked by Jason, but uses the Win32 API exclusively.

popen() alternative

Why aren't you using pipe/fork/exec method?

pid_t pid = 0;
int pipefd[2];
FILE* output;
char line[256];
int status;

pipe(pipefd); //create a pipe
pid = fork(); //span a child process
if (pid == 0)
{
// Child. Let's redirect its standard output to our pipe and replace process with tail
close(pipefd[0]);
dup2(pipefd[1], STDOUT_FILENO);
dup2(pipefd[1], STDERR_FILENO);
execl("/usr/bin/tail", "/usr/bin/tail", "-f", "path/to/your/file", (char*) NULL);
}

//Only parent gets here. Listen to what the tail says
close(pipefd[1]);
output = fdopen(pipefd[0], "r");

while(fgets(line, sizeof(line), output)) //listen to what tail writes to its standard output
{
//if you need to kill the tail application, just kill it:
if(something_goes_wrong)
kill(pid, SIGKILL);
}

//or wait for the child process to terminate
waitpid(pid, &status, 0);

What's equivalent c++ _popen in C#?

Check out:

http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandardoutput.aspx

Here's a snippit:

// Start the child process.
Process p = new Process();
// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "Write500Lines.exe";
p.Start();
// Do not wait for the child process to exit before
// reading to the end of its redirected stream.
// p.WaitForExit();
// Read the output stream first and then wait.
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();

C equivalent to Perl system() or Python subprocess

C does have a system function in its standard library, see e.g. the wikipedia entry about it.

pipe a buffer from my program to another program's stdin using popen

How can I get buffer[] piped directly to otherpgm's stdin using popen()?

This can't be done using popen.

Or some other mechanism

You need to set up two pipes (see man pipe) -- one from your-program to the other-program, and one from other-program to your-program, then fork, close appropriate ends of the pipes in the child and exec other-program.

You also need to worry about deadlocks if the data you need to write or read exceeds PIPE_BUF.

Example code.

Relevant answer -- this can be much easier if you can make a FIFO on disk.

Another answer with examples.

Why does _popen work here, but boost::process does not?

I don't have windows, so I tested it on my linux box, slightly simplified:

#include <boost/process.hpp>
#include <iostream>

namespace bp = boost::process;

int main() {
bp::opstream m_Write;
boost::filesystem::path program("/usr/bin/gnuplot");
bp::child m_Plot(program, bp::std_in = m_Write);

m_Write << "set term png\n";
m_Write << "set output \"Out.png\"\n";
m_Write << "plot \"Data.txt\" using 1:2 notitle\n";
m_Write.flush();
m_Write.pipe().close();

m_Plot.wait();
std::cout << "Done, exit code: " << m_Plot.exit_code() << "\n";
}

Prints:

Done, exit code: 0

And created this nice image from simplistic data:

Windows

On windows, leverage the power of Boost Filesystem's path to do the path:

boost::filesystem::path program("C:\\gnuplot\\bin\\gnuplot.exe");

Other Notes

If the whole script is, indeed, fixed, consider using a raw literal:

m_Write << R"(set term png
set output "Out.png"
plot "Data.txt" using 1:2 notitle)" << std::flush;
m_Write.pipe().close();

subprocess.popen (python) in C

In C, you get the maximum number of options by first calling fork() to create a new process (the eventual subprocess), then one of the exec*() family of functions to execute the subprocess. Both the original process and the new process will run concurrently, so you can exchange (read and/or write data) via pipes or socket pairs. Finally, use e.g. waitpid() in a loop to wait for the new process to exit, and "reap" its exit status. For example:

#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>

int main(void)
{
pid_t child, p;
int status;

/*
* Prepare pipes et cetera first.
*/

/* Fork to create the subprocess. */
child = fork();
if (child == (pid_t)-1) {
/* Cannot fork(); usually out of resources (user limits).
* see errno for details. With <string.h>, you can use
* strerror(errno) to obtain the error string itself. */
return 1;

} else
if (!child) {
/* This is the child process itself.
* Do whatever cleanup is necessary, then
* execute the subprocess command. */
execlp("/bin/ls", "ls", "-lA", NULL);

/* This is only reached if the exec failed;
* again, see errno for reason.
* Always have the child process exit! */
return 127;
}

/* This is only run by the parent process
* (because the child always exits within the
* else if body above).
*
* The subprocess PID is 'child'.
*/

/* Wait for the child process to exit. */
do {
status = 0;
p = waitpid(child, &status, 0);
if (p == (pid_t)-1 && errno != EINTR)
break; /* Error */
} while (p != child);

if (p != child) {
/* Child process was lost.
* If (p == (pid_t)-1), errno describes the error.
*/

} else
if (WIFEXITED(status)) {
/* Child process exited with WEXITSTATUS(status) status.
* A status of 0 (or EXIT_SUCCESS) means success,
* no errors occurred. Nonzero usually means an error,
* but codes vary from binary to binary.
*/

} else
if (WIFSIGNALED(status)) {
/* Child process died from WTERMSIG(status) signal.
* If you include <string.h>, you can use
* strsignal(WTERMSIG(status))
* to obtain the name (string) of the terminating signal.
*/

} else {
/* Child process died from unknown causes.
*/

}

/* All done. */
return 0;
}

Personally, I prefer to use socketpair() to create Unix domain stream or datagram sockets between processes I control, and pipes created via pipe() if the subprocess is just some random binary to be run. In all cases you can replace the standard input (STDIN_FILENO descriptor), standard output (STDOUT_FILENO descriptor), and standard error (STDERR_FILENO descriptor) with sockets or pipes, using the dup2() function. You can even access the pseudo-files under /proc/[child]/ from the parent to observe the state of the child process if you want.

Depending on how you need to communicate with the subprocess -- input/output from/to files? strings in memory? dynamically allocated buffer for output -- there are many variants. Usually code similar to above is used when precise control and/or full-duplex (both read and write) and/or asynchronous communications are needed.

You can do a search for "linux" "fork" "exec" in your favourite search engine for examples of varying quality.


If you want an easier solution, and you only need to capture the output of the command (supplying no input to the command, or perhaps supplying the input from a file), you could use some variant of

#include <unistd.h>
#include <stdio.h>
#include <errno.h>

int main(void)
{
FILE *sub;
pid_t subpid;
int status;

sub = popen("setsid /bin/sh -c 'echo $$ ; exec command args' </dev/null", "rb");
if (!sub) {
/* popen() failed. */
return 1;
}

/* Read the first line from sub. It contains the PID for the command. */
{
char buffer[32], *line, dummy;
int value;

line = fgets(buffer, sizeof buffer, sub);
if (!line) {
/* setsid failed, or non-POSIXy system (Windows?) */
pclose(sub);
return 1;
}
if (sscanf(line, "%d%c", &value, &dummy) != 1 || value < 2) {
/* Internal bug, or extra output? */
pclose(sub);
return 1;
}

/* subpid is also the session ID and the process group ID,
* because it is the session leader. */
subpid = value;
}

/* Read from sub using standard I/O, to capture command output. */

/* After no more output to read from sub, reap the subprocess. */
errno = 0;
do {
status = pclose(sub);
} while (status == -1 && errno == EINTR);

if (status) {
/* Problem: sub exited with nonzero exit status 'status',
* or if status == -1, some other error occurred. */

} else {
/* Sub exited with success (zero exit status). */
}

/* Done. */
return 0;
}

In Linux, popen() uses the /bin/sh shell (as per POSIX.1 specification), and we can use the setsid command-line utility to create the new session. Within the command, the echo $$ is a sh command which outputs the shell PID, and exec CMD... replaces the shell with the command; thus we get the PID of the command even before the command gets executed.

Send data continuously from a c++ file to a Python script for further processing

You are looking for Popen class of the subprocess module in python.

Python equivalent of the C function could be along the lines of

from subprocess import Popen, PIPE

def exec(*args):
with Popen(args, stdout=PIPE) as proc:
while proc.poll() is None:
print(proc.stdout.read(40))
print(proc.stdout.read())

As an alternative solution, you could also wrap the C code in python and call the C API from python. There are several resources online on how to do that.



Related Topics



Leave a reply



Submit