Skip to content

[Rcpp-devel] Redirecting cout/cerr streams to Rprintf

2 messages · Renaud Gaujoux, Romain Francois

#
Hi,

this is somehow a general C++ question, but it could be of interest to all
Rcpp users (I think).

Still for the purpose of RcppOctave, I would like to redirect cout and cerr
streams that are used by Octave to Rprintf REprintf respectively.
Currently I redirect these streams to 2 temporary stringstreams (via the
std::cout.rdbuf get/set methods ) which buffer the output/errors messages
and print them at the end of the Octave call. The standard streams are
restored on exiting the function (in a class destructor).

However, I would like to do this without buffering, i.e. that messages are
printed as they come through the stream. This should be possible through
the definition of a std::stream child class with some method overload that
output the formatted messages as they are pushed into the stream.

Anybody knows which class and method(s) need to be overloaded, or have
hints on how to achieve this in an -- aesthetic -- way?

Thank you.

Bests,
Renaud
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20131021/aae125ce/attachment-0001.html>
2 days later
#
Le 21/10/2013 12:24, Renaud Gaujoux a ?crit :
Hello,

Rcpp11 does this by default now instead of the behavior that is in Rcpp, 
which depends on the Rcpp::Rcout and Rcpp::cerr. See e.g. 
https://github.com/romainfrancois/Rcpp11/blob/master/src/Rcpp11_init.cpp

In Rcpp, you would just have to grab the rdbuf of cout, remember it, set 
it to something different and then later reset it. You can take 
advantage of C++ constructor/destructor anddo something like this:

class Sinker {
public:
     Sinker(): remembered_buffer(std::cout.rdbuf() ){
         std::cout.rdbuf( Rcout.rdbuf() ) ;
     }

     ~Sinker(){
         std::cout.rdbuf( remembered_buffer  ) ;
     }

private:
     std::streambuf* remembered_buffer ;
}  ;

Then, whenever you want this redirection, you just have to create a 
Sinker object:

void foo(){
     Sinker bar ;
     // call whatever that uses cout
}

Romain