Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support generic reading of Feedback #5

Open
acidtonic opened this issue May 23, 2018 · 3 comments
Open

Support generic reading of Feedback #5

acidtonic opened this issue May 23, 2018 · 3 comments

Comments

@acidtonic
Copy link

First, thanks for your work on the project.

I am trying to create an image and dump it to the console instead of through a file. I am able to do so by setting the terminal to pngcairo and avoid setting an output.

It seems that the mechanism to read back from the process is geared towards mouse feedback, but I noticed you have all the required components already in the code, it's just private.

https://github.com/dstahlke/gnuplot-iostream/blob/master/gnuplot-iostream.h#L1821

Can we perhaps adjust things slightly so that allocFeedback is public and can be called by the user, and a public getter for the GnuplotFeedback pointer?

This way I could read the generated png out of the console instead of going to the disk.

My ideal usage would be something like....


gp << "graph commands here";
gp.allocFeedback();
GnuplotFeedback * feedback = gp.feedback //(or a const getter)
gp.send1d(mydata);
File * pngFile = feedback->handle();
//Code to render the file or do whatever here. 
@dstahlke
Copy link
Owner

GnuplotFeedbackPty is actually a separate class from the main Gnuplot class, so you could actually just use it as-is. The feedback member variable in the Gnuplot class is just there to avoid having to re-create the PTY each time. If you want to make that public, feel free to send me a pull request. But you could also just do something like this from your code:

GnuplotFeedbackPty pty(debug_messages);
gp << "set output \"" << pty.filename() << "\"\n";
gp.send1d(mydata);
FILE * pngFile = feedback->handle();

But keep in mind that this mechanism only works in Linux.

@acidtonic
Copy link
Author

This actually was helpful. I didn't think about manually using the class which fits my use case a bit better.

I did however run into a problem which is slightly borderline....

gnuplot when using the pngcairo terminal apparently adds CRLF's to the binary output in the PTY. I am on linux so this was unexpected. Appears to be a bug upstream in gnuplot. To workaround I manually read character by character and used a state machine to skip the CR if the next character is LF. This way I directly have the image binary data without ever touching the filesystem.

But I did have to adjust the mode the GnuplotFeedbackPty opens the handle with to include binary mode and added a getter for the master_fd so I could fcntl the descriptor into non-blocking mode. Otherwise the transient EOFs from the PTY would block fread incorrectly (even with feof) and either give me an incomplete file, or a blocking read past the end.

It was a bit more challenging than I expected but in the end it works fantastically. Thanks for your help!

@dstahlke
Copy link
Owner

I'm glad you got it (sort of) working. It surprises me that you had to open the PTY in binary mode, as I was under the impression that text and binary mode were equivalent on Unix.

Instead of a PTY, you could look into the O_TMPFILE option of open. This creates an unnamed temporary file, never being visible on disk and guaranteed to be deleted if your program crashes. You can then read the file from /proc/self/fd/. Beware that O_TMPFILE only exists in since Linux 3.11.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants