New to CPP and RCPP
I am putting together an R package with RCPP.
Here are my steps:
Transfer to directory with package.
Run compileAttributes(pkgdir = ".",verbose=TRUE)
Then run build and install from devtools.
I want one of my CPP functions to print a message whenever it is invoked.
So i added :
Rcpp::Rcout << "Hello World!" << std::endl;
I then went through steps 1 to 3 above. But no cigar. Not even a cigarillo.
Ideally, I want it to print out an integer value i, somthing like
Sample code.
Rcpp::Rcout << i << std::endl;
SO far, it compiles and the function runs - but no printout of the dear variable. HELP! An example of my function is below. I suspect there is some standard way to either pass the values to R or to simply print from CPP.
# include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::plugins(cpp11)]]
using namespace Rcpp ;
arma::mat sillyme (arma::mat FE) {
arma::mat FEE = FE ;
Rcpp::Rcout << "Hello World!" << std::endl;
Rcpp::Rcout << FE.n_rows << std::endl;
return(FEE) ;
}
On my system (Ubuntu 20.04, R 4.0.0), this works just as expected (after adding a // [[Rcpp::export]] attribute to make sure the function is callable from R):
sillyme(diag(2))
# Hello World!
# 2
# [,1] [,2]
# [1,] 1 0
# [2,] 0 1
Related
I know how to add a progress indicator in a Shiny app using withProgress() (as described here). However, given that my long running computation code calls from a package (that I've written) in which most of the code is written using Rcpp, I don't know how to return a progress value that Shiny can understand from within the Rcpp code. In my Rcpp code, I'm currently using the ones provided in RcppProgress (as described here), but I'm unsure how RcppProgress can communicate with Shiny's withProgress(). If anyone has any alternative suggestions, it'd be much appreciated!
Print out your progress and carriage return to the beginning of the same line. Here's a short example that prints out how much progress you've made:
#include <chrono>
#include <thread>
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
void test(size_t loop_size) {
std::cout.precision(4);
for(size_t i=0; i<loop_size; ++i) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
if(i == loop_size - 1) {
std::cout << "100.0%" << std::endl;
} else if(i % 33 == 0) {
std::cout << static_cast<double>(i+1) / static_cast<double>(loop_size) * 100.0 << "%";
std::cout << "\r";
}
}
}
/*** R
test(10000)
*/
Example
I have an Rcpp function where I would like to call boost::posix_time::time_from_string().
I've taken the example code from the boost documentation and translated it to a c++ function using Rcpp
library(Rcpp)
cppFunction(
includes = '
#include <boost/date_time/posix_time/posix_time.hpp>
',
code = '
void time_test() {
std::string t = "2002-01-20 23:59:59.000";
boost::posix_time::ptime pt(boost::posix_time::time_from_string(t));
Rcpp::Rcout << "time from string: " << pt << std::endl;
}
',
depends = "BH"
)
However, this doesn't compile.
I've seen a few comments saying you need to link to -lboost_date_time, such as this line in Dirk's RcppBDT library
// The next function uses the non-stream-based parsing in Boost Date_Time
// and requires _linking_ with -lboost_date_time which makes the (otherwise
// header-only) build more complicate
// // [ [ Rcpp::export ] ]
// Rcpp::DatetimeVector charToPOSIXctNS(Rcpp::CharacterVector sv) {
// ... code omitted ...
// }
Question
How do you provide the appropriate links to lboost_date_time, other than including the posix_time.hpp header, so that one can use time_from_string()?
Extra Info
It's possible to use other functions from the boost/date_time library, as demonstrated by this function, so what makes time_from_string() different?
cppFunction(
includes = '
#include <boost/date_time/posix_time/posix_time.hpp>
',
code = '
void time_test() {
Rcpp::Datetime dt("2002-01-20 23:59:59.000");
boost::posix_time::hours h( dt.getHours() );
boost::posix_time::minutes m( dt.getMinutes() );
boost::posix_time::seconds s( dt.getSeconds() );
Rcpp::Rcout << h << std::endl;
Rcpp::Rcout << m << std::endl;
Rcpp::Rcout << s << std::endl;
}
',
depends = "BH"
)
time_test()
# 12:00:00
# 00:59:00
# 00:00:59
As you already found out, you need to link with boost at the system level. The BH package is not sufficient. So first you have to install the required boost library. On Debian (dervied) Linux systems this can be done via
sudo apt-get install libboost-date-time-dev
Then you need to tell R to add -I/path/to/boost/headers and -L/path/to/boost/libraries -lboost_date_time to the compiler flags. You can do this by setting appropriate environment variables:
library(Rcpp)
Sys.setenv(PKG_LIBS="-L/usr/lib -lboost_date_time", PKG_CPPFLAGS="-I/usr/include")
cppFunction(
includes = '
#include <boost/date_time/posix_time/posix_time.hpp>
',
code = '
void time_test() {
std::string t = "2002-01-20 23:59:59.000";
boost::posix_time::ptime pt(boost::posix_time::time_from_string(t));
Rcpp::Rcout << "time from string: " << pt << std::endl;
}
'
)
Notes:
One could also define a Rcpp plugin for this.
In my case -I... and -L... are unnecessary, since the library is installed in a standard location. One does need these flags in other cases, though.
I have .txt file named test_file.txt in my AWS S3 bucket stored in the location
s3://path/to/csv/test_file.txt which contains a sample statement like - this is for testing
I can read this file directly from the S3 bucket location using a combination of readLines and pipe statement in R as
df <- readLines(pipe("aws s3 cp s3://path/to/csv/test_file.txt -"))
df
#[1] "this is for testing"
When I try to replicate the same in Rcpp, I write a file rcoo_input_string.cpp as follows
#include <Rcpp.h>
#include <string.h>
// [[Rcpp::export]]
Rcpp::String rcpp_input_test() {
Rcpp::Environment base = Rcpp::Environment("package:base");
Rcpp::Function readline = base["readline"];
Rcpp::Function as_string = base["as.character"];
std::string input_string = Rcpp::as<std::string> (as_string(readline("> ")));
Rcpp::Rcout << input_string << std::endl;
return input_string;
}
/*** R
library(magrittr)
rcpp_input_test()
*/
Note:I got the idea that std::cin wont work in R or Rcpp, so I took inspiration from this post Getting user input from R console: Rcpp and std::cin
I write another file rcoo_input_string.R as follows
library(Rcpp)
sourceCpp("./rcoo_input_string.cpp")
and execute the rcoo_input_string.R file from the AWS CLI as
aws s3 cp s3://path/to/csv/test_file.txt - | Rscript rcoo_input_string.R
but I get the following output on the CLI
> library(magrittr)
> rcpp_input_test()
>
[1] ""
which means that the Rcpp function did not read the test_file.txt.
Please note that running
sourceCpp("./rcoo_input_string.cpp")
runs perfectly well and I can give the input and the Rcpp function returns the string value as well (like this)
> sourceCpp("./S3_to_R_data_import/rcoo_input_string.cpp")
> library(magrittr)
> rcpp_input_test()
> this is for testing
this is for testing
[1] "this is for testing"
Can someone guide me on how to create an input stream for this function in R ?
I say input stream, and please correct me if I am wrong, because I wrote a similar code for a C++ file and it executed perfectly.
Note: In trying to solve this problem, I tried cppFunction too, but that did not not solve the problem. Example of rcoo_input_string_2.R
library(Rcpp)
#sourceCpp("/mnt/legoland/S3_to_R_data_import/rcoo_input_string.cpp")
cppFunction(' String rcpp_input_test() {
Environment base = Environment("package:base");
Function readline = base["readline"];
Function as_string = base["as.character"];
std::string input_string = as<std::string> (as_string(readline("> ")));
Rcout << input_string << std::endl;
return input_string;
}
')
print(rcpp_input_test())
when using Rcpp, I want to use function abs, I just write Rcpp::abs(-1), but always an error:
no matching function for call to abs
Actually when I write Rcpp:ab, there are some hint that there exists Rcpp::abs(). I have tried some other function Rcpp::NumericVector, it works. I know I can use std::abs(-1), I just wonder why Rcpp::abs(-1) do not work, my system is windows, and I install Rtools.
Rcpp::abs() requires an Rcpp object, e.g. *Vector and *Matrix.
Unfortunately, -1 is of a primitive type, e.g. not an Rcpp object.
So, the following would work:
#include <Rcpp.h>
// [[Rcpp::export]]
void show_rcpp_abs() {
Rcpp::NumericVector A = NumericVector::create(-1);
Rcpp::Rcout << "A" << Rcpp::abs(A) << std::endl;
double B = std::abs(-1.0);
Rcpp::Rcout << "B" << B << std::endl;
}
I implemented a Python-style dictionary for R, but did not find a good way to raise an error when a given key does not have a value in the dictionary. Calling stop is easy enough, but I would like to tell the user which key has not been found by printing the R object. Right now I have:
Rcpp::Rcout << "Key not found: ";
Rcpp::print(key); # <-- how can I get this on stderr?
Rcpp::stop("Key error!");
This prints the message to stdout, but I'd rather have it on stderr. Probably I'm just missing a function that Rcpp provides?
Here's a MWE:
library(Rcpp)
sourceCpp(code='
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
void test(SEXP key) {
Rcpp::print(key);
Rcpp::Rcerr << "This does not work: " << key << std::endl;
}
/*** R
test("x")
test(c(1,2,3))
*/
')
This works just fine:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
std::string test(std::string key) {
Rcpp::Rcerr << "Key not found: "<< key << std::endl;
Rcpp::stop("Key error!");
return key;
}
/*** R
test("x")
*/
Output:
Key not found: x
Error in eval(expr, envir, enclos) : Key error!
Edit:
OK, so you pass a SEXP that can be a single value or vector. I would suggest to cast that to a character vector:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
void test(SEXP key) {
CharacterVector key1 = as<CharacterVector>(key);
Rcpp::Rcerr << "This does not work: " << key1 << std::endl;
}
/*** R
test(c("x", "y"))
test(1:3)
*/
Output:
> Rcpp::sourceCpp('E:/temp/ttt.cpp')
> test(c("x", "y"))
This does not work: "x" "y"
> test(1:3)
This does not work: "1" "2" "3"
At the moment, it seems that this hack is the only way to go. It's not very efficient, as we go back from C++ to R to get the value as a nice string.
library(Rcpp)
sourceCpp(code='
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
void test(SEXP key, Function generate_error) {
std::string s = as<std::string>(generate_error(key));
stop(s);
}
/*** R
generate_error <- function(key) {
paste("Key not found:", capture.output(print(key)))
}
try( test("x", generate_error) )
try( test(c(1,2,3), generate_error) )
*/
')
Rcpp calls Rf_PrintValue internally. I've glanced at R source and it seems like this function is in turn implemented using printfs.
So, the problem is how to redirect external printf calls to stderr. Depending on your platform you have multiple options like dup/freopen/CreatePipe etc. Arguably, redirecting stdout back and forth is a hack.