How to interface with an executable in C++ - c++

I have an executable that I need to run some tests on in C++ - and the testing is going to take place on all of Windows, Linux and Mac OSes.
I was hoping for input on:
How would I interface with the previously built executable from my code? Is there some kind of command functionality that I can use? Also, since I think the commands change between OSes, I'd need some guidance in figuring out how I could structure for all three OSes.
EDIT - Interface = I need to be able to run the executable with a command line argument from my C++ code.
The executable when called from the commandline also ouputs some text onto a console - how would I be able to grab that ouput stream (I'd need to record those outputted values as part of my tests).
Feel free to ask me follow up questios.
Cheers!

If you use qt to develop your code, you'll find QProcess will allow you to spawn a command line program in a platform-agnostic way.
Essentially:
QObject *parent;
QString program = "yourcommandlineprogram";
QStringList arguments;
QProcess *myProcess = new QProcess(parent);
myProcess->start(program, arguments);
You can then read from the process with various function calls such as readAllStandardOutput (), and write to the input of the process with QProcess::write(QString).
Alternatively, if you prefer Boost to Qt, Boost.Process will also let you launch processes. I confess I don't like the syntax as much...
boost::process::command_line cl("yourcommandlineprogram");
cl.argument("someargument");
boost::process::launcher l;
l.set_stdout_behavior(bp::redirect_stream);
l.set_merge_out_err(true);
l.set_work_directory(dir);
boost::process::child c = l.start(cl);
You can then work with your subprocess 'c' by using stream operators << and >> to read and write.

All those OSes support some form of "subprocess" calling technique, where your tester creates a new child process and executes the code under test there. You get to not only pass a command line, but also have the opportunity to attach pipes to the child process' standard input and output streams.
Unfortunately, there is no standard C++ API to create child processes. You'll have to find the appropriate API for each OS. For example, in Windows you could use the CreateProcess function: MSDN: Creating Processes (Windows).
See also Stackoverflow: How do you spawn another process in C?

As I understand, you want to:
Spawn a new process with arguments not known at runtime.
Retrieve the information printed to stdout by the new process.
Libraries such as QProcess can spawn processes, however, I would recommend doing it by hand for both Windows and MacOS/Linux as using QProcess for this case is probably overkill.
For MacOS/Linux, here's what I would do:
Set up a pipe in the parent process. Set the read end of the pipe to a new file descriptor in the parent.
fork.
In newly created child process, set stdout (file descriptor #1) to the write end of the pipe.
execvp in the newly created child process and pass the target executable along with what arguments you want to give it.
From the parent process, wait for the child (optional).
From the parent process, read from the file descriptor you indicated in Step 1.

First of all, is it possible that you simply need to want to make your original code reusable? In that case you can build it as library and link it in your new application.
If you really want to communicate with another executable then you can need start it as a subprocess of the main application. I would recommend the Process class of the Poco C++ libraries.

Looks like a job for popen(), available on Linux, Windows, and OS X

Sounds like you are only planning to do functional testing at the executable level. That is not enough. If you plane to do thorough testing, you should also write unit tests. For that there is some excellent frameworks. My prefered one (by far) for C++ is BOOST::Testing.
If you control source code there is also common tricks for functional testing beside launching exe from an external process : embed functional tests. You just add an option to your program that execute tests. This is cool because tests are embedded in code and autocheck can easily be launched in any execution environment.
That means that in the test environment, as you call your program with some test dedicated arguments, nothing keeps you from going the full way and redirect the content of stdout and even check the tests results from within the program. It will make the whole testing much easier than calling from an external launcher, then analysing the results from than launcher.

Related

Invoking a console application from C++ program

I have an console application 'app.exe', which i want to invoke from a C++ program and then communicate with it as if it was a command line. Essentially I want to make a C++ wrapper around another console application so that I could pass input to it at will and receive output.
In pseudo-code something like:
std:string input("...some parameters..."), output;
Process app("app.exe");
app.InputOutput(input, output);
std::cout<<output;
This must have been answered already, but I seem to lack proper terminology to look it up.
In case it matters, I am running Eclipse CDT on Windows 10 with GCC 5.3.0
EDIT: I need to be able to repeatedly send some values to 'app.exe' and repeatedly receive response, rather than just invoke it with parameters. This is needed for a small personal project so I do not care about it being platform-specific.
I used this code as a starting point, in an MFC dialog, to display output from a called process. It was rather painless as this is well documented. He tells you why he is doing what. It should be suitable as you are working with the Windows platform. But as Alf points out, cross platform is something else.
You can use the system function to invoke a shell (command line) command.
That command can be to execute a program with the arguments you want.
system returns the process exit code, but for other results there is no direct support. One easy way to access the output, for a program that just does a job and ends, is to redirect the program's output to a file.
Otherwise you'll have to use communication mechanisms such as pipes or Windows mailslots, that are not supported by the C++ standard library, i.e. you're then into platform-specific code.

C++ execute many commands in shell

I have a C++ program from which I want to execute multiple commands in a shell.
My current solution use the system() function and looks like this:
return_value = system(SETUP_ENVIRONMENT; RUN_USEFUL_APP_1);
... do_something_else ...
return_value = system(SETUP_ENVIRONMENT; RUN_USEFUL_APP_2);
... do_something_else ...
return_value = system(SETUP_ENVIRONMENT; RUN_USEFUL_APP_3);
...
It works, but SETUP_ENVIRONMENT takes a few seconds making the program really slow. But I have to run it every time since system() runs in a new shell each time.
I want to be able to setup my shell once and then run all commands in it.
execute_in_shell(SETUP_ENVIRONMENT);
return_value = execute_in_shell(RUN_USEFUL_APP_1);
... do_something_else ...
return_value = execute_in_shell(RUN_USEFUL_APP_2);
... do_something_else ...
return_value = execute_in_shell(RUN_USEFUL_APP_3);
...
How do I do that?
I'm on Linux.
Alternatively to answer 1, you could also use your program to create a shell script which will run all your useful programs and execute this script at once. Then the shell won't be started each time for each particular useful program.
You have three reasonable options for doing this, depending on your specific need.
If the various calls you make to external tools are part of coherent routine, then you can – and probably should – follow #dmi's advice and write a short shell script that you can call from your C++ program.
If you instead need to start procedures here and there, you might be interested into running the shell as an inferior process and attaching your program to it – so that instead of talking with your terminal, the shell process talks to your C++ program.
This method is not very difficult but has a few gotchas (for instance, some programs like ssh, sudo or docker may expect to be attached to a tty). It is very well covered in most introductions to system programming (look for inter process communication and subprocesses) for any Unix variant. Let me outline that procedure:
use the pipe system call to create pipes (stdin_r, stdin_w)
use the pipe system call to create pipes (stdout_r, stdout_w)
use the pipe system call to create pipes (stderr_r, stderr_w)
use the fork system call to duplicate your program
In the child, you close stdin_w, stdout_r, stderr_r, and use the
exec system call parametrised by stdin_r, stdout_w, stderr_w to
run the shell.
In the parent, you close stdin_r, stdout_w, stderr_w, and you
can now write commands in stdin_w, and read command output from
stdout_r and stderr_r.
(This intentionally very sketchy, I included the outline only so that you are sure you found the right place in your favourite textbook).
There are third party libraries implementing all that low-level stuff for you. You can use boost::process (which is not yet an official part of boost now) whose usage is illustrated with a full tutorial. There are plenty of alternatives such as pstreams.
The third option would be to avoid using the shell and executing directly shell commands you use. This is the approach followed by Rashell, an OCaml library defining primitives allowing to reliably compose sub-processes, which you can use for your own inspiration.

Open a process from file, in C++ on Linux

I'm coding my application in C++ on Linux. C++ has a function called 'system' to execute a programme.
I try to open the gnome-system-monitor from C++ like this:
system("gnome-system-monitor");
However, the thread of my application blocks when I call this 'system' function until I close the window of gnome-system-monitor.
Any other ways to open a process from file without blocking the caller process?
The classic way, which works on any Linux or otherwise POSIX-based system, is
if (0 == fork()) {
execlp("gnome-system-monitor", "gnome-system-monitor", (char *)NULL);
}
(with error handling omitted from this example.) This (a) creates a new process, (b) in that new process, runs "gnome-system-monitor" after searching the PATH environment variable to find such a command, (c) passes it the name "gnome-system-monitor" as argv[0] and no other arguments. In the parent, once the new process is created it barrels on ahead without waiting for any result.
See the man pages for fork and execlp for more details.
fork/exec or posix_spawn. glib also has GSpawn if you are using that.
Gnome is built above GTk (which contains Glib), and you probably want the Glib Spawning Processes functions.
Of course, on Linux and Unix, processes are forked. Read a good book like
advanced unix programming and advanced linux programming to learn more about syscalls related to processes, notably fork(2), execve(2), pipe(2). Read also about the proc(5) filesystem.
Yes. Call System function on a separte thread.

Communication with a script from a C++ program

I have a c++ program (very complicated, and lengthy both in code and execution time).
Once in a while this program stops and calls a user-specified shell script.
Before calling the script, my program creates a .out file with current data. I call the script via system() command. The script then reads the .out file, and creates its own script.out file and exits.
Then the system() function call ends, and my program reads and parses the script.out file.
Question: is there a better way to execute communication between my c++ program and a random shell script?
My intent is to have full communication between the two. Script could virtually "ask" the program "What data do you have right now?" and the program would reply with some strict convention. Then the script could say "Add this data...", or "delete all your previous data" etc.etc.
The reason I need this is because the shell script tells the program to modify its data. The exact data that was put in the original .out file. So after the modification is done -- the actual data held by the program does not correspond to the data written in the .out file.
Thanks!
P.S.
I swear I've searched around, but everyone suggests an intermediate file.
There are certainly ways to do that without intermediate files. The most common approach is to use command line arguments for input, and pipes for standard output; others also use pipes for input. The most straight-forward alternative to system then is to use popen.
On a unix-like system? Perhaps pipe (2) will work for you?
From the man page (Mac OS X 10.5 version):
SYNOPSIS
#include <unistd.h>
int pipe(int fildes[2]);
DESCRIPTION
The pipe() function creates a pipe (an object that allows unidirectional
data flow) and allocates a pair of file descriptors. The first descrip-
tor connects to the read end of the pipe; the second connects to the
write end.
You will, of course, have to follow the creation of the pipes with a fork and exec pair. Probably this has already been answered in detail, and now you know what to search on...
It's been a while since I did this, but:
In the main process, before forking the sub-process you call pipe twice. Now you have two pipes and control both ends of both of them.
You fork.
The main process will read from one pipe and write from the other. It doesn't matter which is which, but you need to be clear about this.
The child process will call one of the exec family of function to replace it's image with that of the shell you want to run but first you will use dup2 to replace it's standard input and output with the ends of the two pipes (again, this is where you need to be clear about which pipe is which).
At his point you have two processes, the main process can send things into one pipe ad they will be received on the standard input of the script, and anything the script writes to it's standard output will be sent up the other pipe to the controlling process. So they take turns, just like interacting with the shell.
You can use pipes or (maybe more convenient) sockets - for example frontends to gdb, or expect do that. It would require changes to your shell scripts, and switching from system() to more low-level fork() and exec().
It's rather complicated so please, be more specific about your environment and what you need to clarify.
You are asking the question on Interprocess Communication (IPC).
There are a lot of ways to do that. You can do a simply search and Internet will return you most answers.
If I am not wrong, Google chrome uses a technique called Named Pipe.
Anyway, I think the most "portable way" is probably a file. But if you know you are working on which operating system, you can definitely use most of the IPC techniques.

Crossplatform Bidirectional IPC

I have a project that I thought was going to be relatively easy, but is turning out to be more of a pain that I had hoped. First, most of the code I'm interacting with is legacy code that I don't have control over, so I can't do big paradigm changes.
Here's a simplified explanation of what I need to do: Say I have a large number of simple programs that read from stdin and write to stdout. (These I can't touch). Basically, input to stdin is a command like "Set temperature to 100" or something like that. And the output is an event "Temperature has been set to 100" or "Temperature has fallen below setpoint".
What I'd like to do is write an application that can start a bunch of these simple programs, watch for events and then send commands to them as necessary. My initial plan was to something like popen, but I need a bidrectional popen to get both read and write pipes. I hacked something together that I call popen2 where I pass it the command to run and two FILE* that get filled with the read and write stream. Then all I need to do is write a simple loop that reads from each of the stdouts from each of the processes, does the logic that it needs and then writes commands back to the proper process.
Here's some pseudocode
FILE *p1read, *p1write;
FILE *p2read, *p2write;
FILE *p3read, *p3write;
//start each command, attach to stdin and stdout
popen2("process1",&p1read,&p1write);
popen2("process2",&p2read,&p2write);
popen2("process3",&p3read,&p3write);
while (1)
{
//read status from each process
char status1[1024];
char status2[1024];
char status3[1024];
fread(status1,1024,p1read);
fread(status2,1024,p2read);
fread(status3,1024,p3read);
char command1[1024];
char command2[1024];
char command3[1024];
//do some logic here
//write command back to each process
fwrite(command1,p1write);
fwrite(command2,p2write);
fwrite(command3,p3write);
}
The real program is more complicated where it peeks in the stream to see if anything is waiting, if not, it will skip that process, likewise if it doesn't need to send a command to a certain process it doesn't. But this code gives the basic idea.
Now this works great on my UNIX box and even pretty good on a Windows XP box with cygwin. However, now I need to get it to work on Win32 natively.
The hard part is that my popen2 uses fork() and execl() to start the process and assign the streams to stdin and stdout of the child processes. Is there a clean way I can do this in windows? Basically, I'd like to create a popen2 that works in windows the same way as my unix version. This way the only windows specific code would be in that function and I could get away with everything else working the same way.
Any Ideas?
Thanks!
On Windows, you invoke CreatePipe first (similar to pipe(2)), then CreateProcess. The trick here is that CreateProcess has a parameter where you can pass stdin, stdout, stderr of the newly-created process.
Notice that when you use stdio, you need to do fdopen to create the file object afterwards, which expects file numbers. In the Microsoft CRT, file numbers are different from OS file handles. So to return the other end of CreatePipe to the caller, you first need _open_osfhandle to get a CRT file number, and then fdopen on that.
If you want to see working code, check out _PyPopen in
http://svn.python.org/view/python/trunk/Modules/posixmodule.c?view=markup
I think you've made a very good start to your problem by using the popen2() function to abstract away the cross-platform issues. I was expecting to come and suggest 'sockets', but I'm sure that's not relevant after reading the question. You could use sockets instead of pipes - it would be hidden in the popen2() function.
I am 99% sure you can implement the required functionality on Windows, using Windows APIs. What I cannot do is point you to the right functions reliably. However, you should be aware the Microsoft has most of the POSIX-like API calls available, but the name is prefixed with '_'. There are also native API calls that achieve the effects of fork and exec.
Your comments suggest that you are aware of issues with availability of data and possible deadlocks - be cautious.