Hello monks -

I am building a GUI REPL with Prima. One major part of this is to capture the output of print, printf, warn, etc. Not a trivial problem, but solvable. A simple solution is given on Stack Overflow and serves as the basis for my current work. Basically, you create a tied file handle and either select() it or assign STDOUT (and STDERR) to it. Simple. However, all is not well. I have a REPL, remember, and it's not hard to generate an Inline block that uses C's printf. Unfortunately, the output of this printf statement does not get captured!

I was recently directed to Capture::Tiny and thought, "This is exactly what I need!" Almost. For long running XS functions, I like to print output to the screen using something like

... printf("On step %d\n", i); ...

I would *really* like to have the output screen update with each round of that printout, but Capture::Tiny won't work with tied file handles. It unties them and directs the results to the tie only at the end of the "captured" code. No matter how I implement that, I won't get the output until after the XS function returns.

Not to be dismayed, I dug into Capture::Tiny to see if I could extract the goodies, and that is where I'm stuck. It looks like the way to override STDOUT, in both Perl and underlying XS functions, is to call

open *NEWHANDLE, ">&STDOUT",

but do you notice the catch? The open command creates the new file handle for me. But unless I'm mistaken, that's what the tie operation is supposed to do! They both want to create the new file handle for me, which means I either get the tying behavior or I get the full STDOUT overriding, but not both.

At this stage, I'm beginning to believe that the only real way to keep the REPL responsive and have it print every single output is to have it fork a separate Perl process (an eval daemon, so to speak) and capture the output of the process. This gets pretty crazy, though, because I'm actually targeting PDL, and I have a plotting library that I would like to have open new tabs when you create new plots. Neither PDL nor Prima are Perl threadsafe, so they'd have to be their own processes and I'd probably have to communicate over sockets. Since neither are threadsafe, I don't know how to share data between the two processes, which means that for good plotting, they would both need a copy of the data... You can see that this is turning the whole thing into a much larger project. It might not be a bad direction to eventually take, but it's not where I want to go at the moment.

If I can't universally capture XS output without creating an eval daemon, I have one last hope, which is to direct my users to use a special C function to print their output. I assumed that PerlIO_stdoutf would have been that function, but it turns out not to be the case. The only remaining idea I have is to suggest the creation of a C function that explicitly calls Perl's print by explicitly calling Perl code from within C.

But surely there's a better solution?


In reply to Capturing XS printf output with a tied filehandle by run4flat

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.