Opening this as per request of @kevinushey. As explained in this thread,
Rcoutis defined iniostream/Rstreambuf.has a static object. This means that different translation units see a differentRcout, while they see the samestd::cout(I have a minimal package showing this if needed). As a result, for example, one object allocated in a certain cpp cannot redirect the output of other object allocated in another cpp.
And the same for Rcerr. I think that this might be worth fixing on the Rcpp side, but probably it would require to declare Rcout and Rcerr as extern and generate some code to initialise them in RcppExports.cpp.
This issue is stale (365 days without activity) and will be closed in 31 days unless new activity is seen. Please feel free to re-open it is still a concern, possibly with additional data.
I think this is still worth fixing.
Sure. Any chance you could take a stab at it in branch?
Yes, I would like to. I'll try to find some time for this in the coming weeks. My approach would be to follow the design of std::cout if there is no complication that I'm not aware of.
There's a first pass at this here: https://github.com/Enchufa2/Rcpp/commit/d96d8063943db680aaafacd7d38714feaf92445f. I would like to ensure that this is the right approach before submitting a PR. Basically I have:
Rcout and Rcerr (previously static objects) as extern references;Rcpp_cout_get and Rcpp_cerr_get, that create static objects and return a reference to them.Now the problem is that the initialization of such references must be part of the scaffolding code. For example, in RcppExports.cpp, in calls to cppFunction, sourceCpp... So far, I've managed to make this work:
f <- "CharacterVector ptr%s() {
std::ostringstream address;
address << (void const *)(&%s);
return address.str();
}"
Rcpp::cppFunction(sprintf(f, "A", "Rcout"))
Rcpp::cppFunction(sprintf(f, "B", "Rcout"))
ptrA() == ptrB() # should be TRUE
So:
BTW, a motivating example that could be used for testing:
Rcpp::cppFunction('void to_left() { Rcout << std::left; }')
Rcpp::cppFunction('void something() { Rcout << std::setw(20) << "something" << std::endl; }')
something() # right-aligned by default
to_left() # change alignment
something() # should be left-aligned
This is the kind of thing that bit me when I opened this, but in the context of two different .cpp files in a package. It took a while to find out what was happening, because there's a single stdout, a single std::cout, and similarly one expects a single Rcpp::Rcout.
Right. Rcout support was a reasonably early contribution that hugely helpful in coordinating with the R i/o streams. It hasn't really been revisited since. Switching, possibly optionally, to this new scheme would be nice. I guess you are in a man-to-man combat with the Attributes code here combined for good measure with the non-trivial initialization code.
By some quick trial and error, I managed to get this pass all the tests except for the use of Rcout in the context of sourcing a file with sourceCpp. I need more study of that part of the code.
Never mind. That comment was meant for our Twitter DM stream. Redacted here.
I'm a little worried that re-defining Rcout / Rcerr in this way could be brittle, in that it could be easy to miss places where Rcout / Rcerr should have been initialized, but weren't.
What do you think about instead defining Rcout() and Rcerr() functions, that return a reference to a static object living in the Rcpp library? So one could do:
Rcout() << do << the << thing;
and get the expected result.
Give #1139 an opportunity, please. :) The advantage is that all the code out there will work just by setting a flag.
The rev.dep machine has already been turned on :)
No new issues, as we expected given that an #ifdef shields things: https://github.com/RcppCore/rcpp-logs/commit/fffe2d323710038326d4bda9cc0e4409fdad9887
I wouldn't expect any issue with the new define set either.
Right. Which gets us to a next point: could you possibly cook up an example or better still a unit test?
(The PR had a "tag" for it but no "closes #928" so doing this by hand, with a tip-of-the-hat and _Thank You!_ for the PR!