Hi Rob,

from reading the rest of this thread, I figure your real problem is to capture the stdout of an XS routine.

The key thing to note here is that, within the C routine, stdout corresponds to fileno 1. So, in your Perl code, you'll need to arrange for things to read the output written to exactly that filehandle, e.g. by setting up a pipe to it.

This a bit more involved than you might think, but the following should do the trick (to keep the example concise, I'm using Inline here, but it should equally work with regular XS code):

#!/usr/bin/perl use Inline C => <<'EOC'; void foo() { printf("something being sent to stdout\n"); fflush(stdout); } EOC my $output; { # save original STDOUT open my $saved_stdout, ">&STDOUT"; # create a pipe, which we'll use to read from our own STDOUT local(*RH, *WH); pipe RH, WH; # connect the writing side of the pipe to STDOUT, with # STDOUT being (and remaining) fileno 1 (!) open STDOUT, ">&WH" or die "open: $!"; # debug: verify that fileno really is 1 printf STDERR "fileno(STDOUT): %d\n", fileno(STDOUT); # call the C/XS function whose stdout we want to capture foo(); # close WH to avoid buffering issues (pipes are buffered) close WH; # read output (one line) $output = <RH>; close RH; # restore original STDOUT open STDOUT, ">&", $saved_stdout or die "open: $!"; } print "output of foo(): $output";

prints:

fileno(STDOUT): 1 output of foo(): something being sent to stdout

The crucial thing is that STDOUT has to correspond to fileno 1, so localising STDOUT will not work here (local *STDOUT will result in a new fileno...). For the same reason, you can't use "open-to-a-string", because in that case the filehandle will be a Perl internal one (fileno -1), which the C side knows nothing about...

With the above code, the open STDOUT, ">&WH" is doing a dup2 system call (among other things), which (in this particular case) will first close STDOUT and then immediately reassign that same fileno, which is 1. BTW, this works only if you haven't messed with Perl's STDOUT before (by default, it is fileno 1).

To get a deeper understanding of the mechanics under the hood, you might want to play around with tracing system calls (i.e. strace and friends).  HTH.


In reply to Re: Overloading print() by almut
in thread Overloading print() by syphilis

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.