3

I am trying to plot graphs using GNUPLOT which is a command line interface. But I need to integrate it in c program, so that if program gets executed, graph is plotted. This can be done by using popen command. I have made a code where I am doing popen("gnuplot","r") so now when I execute the program, gnuplot starts. But I need to send multiple commands like popen("sin(x)","r") after popen("gnuplot","r") so that a sin graph is plotted when I execute the code. But i dont know how to pass multiple commands.Please tell me how can I pass multiple commands using popen.Please help thanks?

Here is the code which I am using to send single command:

#include <stdio.h>

int main()
{
    FILE *fp;
    int status;
    fp = popen("gnuplot","r");

    pclose(fp);

    return 0;
}
Ali
  • 43
  • 1
  • 4
  • Possible answer to your question here :(http://stackoverflow.com/questions/23288808/running-multiple-commands-using-popen-in-c) – JBiss Apr 23 '15 at 16:43
  • 1
    You don't call `popen` for each gnuplot command. You write to the file pointer to give gnuplot commands. – amaurea Apr 23 '15 at 16:44
  • You probably would better like to use the `fork()`/`exec*()` approach along with redirecting `stdin` and `stdout` using `dup2()` like for example shown in this answer: http://stackoverflow.com/a/12839498/694576 – alk Apr 23 '15 at 17:11

2 Answers2

2

You should write, not read, to gnuplot, so try:

FILE *fp = popen("gnuplot","w");
if (!fp) { perror("popen gnuplot"); exit(EXIT_FAILURE); };
fprintf(fp, "plot sin(x)/x\n");
fflush(fp);

Don't forget to pclose(fp) where you are done. But this will probably close the plotted graph. See the §7.8 question of gnuplot FAQ

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • 1
    You'll also likely want to either `fflush(fp)` after each command or set line-buffered mode via `setvbuf(fp, 0, _IOLBF, 0)`. Otherwise it's likely that nothing will happen until you close the stream. – R.. GitHub STOP HELPING ICE Apr 23 '15 at 16:57
  • Thanks for this code but what does this EXIT_FAILURE do.? is this same as exit(0). and when I am executing the code, graph is plotted but only for 2sec, why is this happening? – Ali Apr 23 '15 at 16:58
  • Perhaps you should not call `pclose` before you want the plotted graph to disappear. – Basile Starynkevitch Apr 23 '15 at 17:02
  • yes I have done that but still the problem is there.! – Ali Apr 23 '15 at 17:05
2

Once you have called popen(), your file descriptor 'fp' is open and allows you to write data through it which the gnuplot command will see as input. Note that the type should be what you want to do with the pipe, not what the command will do with it, so you should use 'w' since you want to write. And you can issue multiple commands in sequence until you're done.

For example:

#include <stdio.h>

int main()
{
    FILE *fp;
    int status;
    fp = popen("gnuplot","w");
    fprintf(fp, "plot sin(x)\n");
    fprintf(fp, "plot tan(x)\n");

    pclose(fp);

    return 0;
}

Will send "sin(x)" and "tan(x)" followed by newlines through the pipe where gnuplot can read it as input.

Moldova
  • 1,641
  • 10
  • 13
  • This is great but the graphs is plotted only for 2sec and then the window closes automatically, why is this happening? – Ali Apr 23 '15 at 16:59
  • Because as soon as you close the file descriptor, gnuplot sees end of file on its input which it interprets as the user closing the session, so it exits. If you want it to stay open, you have to hold the file open. – Moldova Apr 23 '15 at 17:14
  • so you are saying i should not include pclose(fp), i have done that too but the problem is still there.! – Ali Apr 23 '15 at 17:17
  • That's because as soon as your program exits, the operating system closes all its file descriptors for it. So the program has to remain running in order to hold the pipe open like this. – Moldova Apr 23 '15 at 17:20
  • So what should I do.? – Ali Apr 23 '15 at 17:23
  • It depends on what you're really trying to accomplish. If you just want to display the graph for a fixed period of time and then close, you can sleep that long before exiting. If you want the user to have control, you could read input from the user and only close the pipe after the user has closed your input. I guess there may be other options but it all depends on what you really want to do. – Moldova Apr 23 '15 at 17:29
  • is this possible to plot real time graph using this.? – Ali Apr 23 '15 at 17:44
  • I'm not a real expert on gnuplot itself, but if the main program runs in a loop and gathers some data, it could write that data periodically through the pipe to gnuplot, and gnuplot should then do whatever it would do if you input that via the command line. So I think the answer is yes, you should be able to update it periodically because gnuplot will remain running and continue to read whatever you send it over the pipe. – Moldova Apr 23 '15 at 17:48
  • thats awesome, thanks. last thing I want to know that is there any other alternative to gnuplot because i am also not expert in it. – Ali Apr 23 '15 at 17:50
  • A google search for "gnuplot alternatives" does show a bunch of suggestions, but I am not in a position to make any recommendations about them. – Moldova Apr 23 '15 at 17:58
  • 1
    You must pass the persist option when opening the pipe, `fp = popen("gnuplot -persist", "w"); ` – Christoph Apr 23 '15 at 18:12
  • @Christoph Thanks a lot, including -persist is working. Can you tell me what does this -persist do.? – Ali Apr 24 '15 at 04:42
  • @MarcFraioli can you help in updating my graph like a real time graph? – Ali Apr 24 '15 at 07:29