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.
Related
I've got two Rcpp-wrapped classes, A and B. A's constructor extracts some information from its parameter, and prints it out to prove it worked.
B takes an object of A as a constructor parameter — and reports an error as if extraction in A's constructor failed. But as A did print out the extracted data, it couldn't fail.
How do I get B to accept A as a parameter without erroring out?
Minimal reproducible example:
library(Rcpp)
Rcpp::sourceCpp(code='
#include <Rcpp.h>
struct A {
Rcpp::NumericVector y;
A(Rcpp::List x)
: y(Rcpp::as<Rcpp::NumericVector>(x["foo"]))
{
Rcpp::Rcout << y;
}
};
struct B {
B(A x) { }
};
RCPP_MODULE(A) {
Rcpp::class_<A>("A")
.constructor<Rcpp::List>();
}
RCPP_MODULE(B) {
Rcpp::class_<B>("B")
.constructor<A>();
}
')
Aobj <- new(A, list(foo=1:3))
Bobj <- new(B, Aobj)
Output:
> source('testcase.R', echo=TRUE)
> library(Rcpp)
> Rcpp::sourceCpp(code='
+ #include <Rcpp.h>
+
+ struct A {
+ Rcpp::NumericVector y;
+
+ A(Rcpp::List x)
+ : y(Rcpp::as<Rcpp::NumericVector> .... [TRUNCATED]
> Aobj <- new(A, list(foo=1:3))
1 2 3
> Bobj <- new(B, Aobj)
Error in new_CppObject_xp(fields$.module, fields$.pointer, ...) :
Index out of bounds: [index='foo'].
>
I'll try to explain why your solution works. With RCPP_MODULE(A) you are exposing the C++ struct A as a reference class in R. That is done automatically. However, when you call Bobj <- new(B, Aobj), there is no information how to convert from this reference class to the required C++ struct. By using RCPP_EXPOSED_CLASS(A) you are creating specialization of Rcpp::wrap and Rcpp::as to convert between C++ and R objects in both ways. Since we are only missing the R to C++ conversion, i.e. Rcpp::as, the following is also enough:
#include <RcppCommon.h>
struct A;
RCPP_EXPOSED_AS(A)
#include <Rcpp.h>
struct A {
Rcpp::NumericVector y;
A(Rcpp::List x)
: y(Rcpp::as<Rcpp::NumericVector>(x["foo"]))
{
Rcpp::Rcout << y;
}
};
struct B {
B(A x) { }
};
RCPP_MODULE(A) {
Rcpp::class_<A>("A")
.constructor<Rcpp::List>();
}
RCPP_MODULE(B) {
Rcpp::class_<B>("B")
.constructor<A>();
}
/*** R
Aobj <- new(A, list(foo=1:3))
Bobj <- new(B, Aobj)
*/
When things are not working, it's good to (re-)read some documentation. Specifically, Rcpp Extending (PDF), section 3.2.
I added the following at the beginning of the C++ code:
#include <RcppCommon.h>
struct A;
RCPP_EXPOSED_CLASS(A);
…and it works fine now. I admit I don't fully understand what happens here yet, but this solution is solving both the MWE and my original code problems.
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;
}
New to Rcpp I am testing how to retrieve and use a nested list from R with a known structure without copying parts of the list again. The small code example (with embedded R code) seems to work (cout is used for debugging).
The list rL retrieved from R may be very big so I do not want to reallocate memory (copy parts of rL). Do the current code copy parts of rL?
Best Lars
#include <Rcpp.h>
#include <iostream>
using namespace Rcpp;
using namespace std;
// [[Rcpp::export]]
SEXP testing(const List rL) {
List L(rL);
SEXP sL2(L["L2"]);
List L2(sL2);
SEXP sStateGrpL2(L2["stateGroups"]);
List stateGrpL2(sStateGrpL2);
SEXP sStateAllocL2(L2["stateAlloc"]);
CharacterVector stateAllocL2(sStateAllocL2);
SEXP sActionGrpL2(L2["actionGroups"]);
List actionGrpL2(sActionGrpL2);
SEXP sActionAllocL2(L2["actionAlloc"]);
List actionAllocL2(sActionAllocL2);
vector<string> stateLabels;
vector<string> actionLabels;
CharacterVector actionNames;
for(int n2 = 0; n2< as<int>(L2["stages"]); n2++) {
stateLabels = as< vector<string> >(stateGrpL2[as<string>(stateAllocL2[n2])]);
int s2Size = stateLabels.size();
SEXP sAllocA(actionAllocL2[n2]);
List allocA(sAllocA);
actionNames = as<CharacterVector>(allocA[0]);
cout << "stage:" << n2 << " sN:" << as<string>(stateAllocL2[n2]) << "\n";
for (int s2=0; s2<s2Size; ++s2) {
cout << " s:" << stateLabels[s2] << " aN:" << actionNames[s2] << "\n";
actionLabels = as< vector<string> >(actionGrpL2[ as<string>(actionNames[s2]) ]);
int a2Size = actionLabels.size();
for (int a2=0; a2<a2Size; ++a2) {
cout << " a:" << actionLabels[a2] << "\n";
}
}
}
return wrap(0);
}
/*** R
L <- list( L2=list(stages=2,
stateGroups=list(s1Grp=c("a","b","c"),s2Grp=c("d","e")),
stateAlloc = c(rep("s1Grp",1),rep("s2Grp",1)),
actionGroups = list(a1Grp=c("terminate","keep"), a2Grp=c("finish")),
actionAlloc = list(list( rep("a1Grp",3) ),
list( c("a1Grp","a2Grp") )
)
)
)
testing(L)
*/
You write:
The list rL may be very big so I do not want to use new memory (copy
parts of rL). Is this the way to do it?
Pretty much (as far as I can tell from a glance at your code).
All exchange with R uses SEXP types where the P stands for pointer -- these are shallow proxy objects which will not be copied. It uses / reuses the R object memory.
So if you profile / memory-profile this it should behave similarly for N=10 and N=1e5. But the proof is in the pudding...
A few things :
The loop test n2< as<int>(L2["stages"]) is both hard to read and
inefficient as it is calculated at each iteration. You should
definitely do it just once.
All of your as< vector<string> > create deep copies and does not
take advantage of the R's string cache. Can't you use a
CharacterVector instead ?
I'm working on turning some MCMC software written in c++ into an R-package using Rcpp and modules. In this regard I need to maintain a pointer that is a global variable, and that points to the latest object of some class constructed.
Here is a very simple example in the form of an R-script:
require(Rcpp)
require(inline)
inc <- '
using namespace Rcpp;
class test;
test* glob; //global pointer
class test{
private:
double foo;
public:
test(double foo_) : foo(foo_) {
glob=this; // the line causes segfault
};
double get_foo(){return foo;};
};
RCPP_MODULE(test){
class_<test>("test")
.constructor<double>()
.property("foo",&test::get_foo)
;
}
'
fx <- cxxfunction(signature(),plugin="Rcpp",include=inc);
test_module <- Module("test",getDynLib(fx))
test <- test_module$test
t1 <- new(test,1.0)
What I'm trying to get at is something like the following (in c++):
#include<iostream>
class test;
test* glob;
class test{
private:
double foo;
public:
test(double foo_) : foo(foo_) {glob=this;};
double get_foo(){return foo;};
};
int main(){
test t1(1.0);
test t2(2.0);
std::cout << (*glob).get_foo() << std::endl;
}
Which compiles and runs as it should.
Thanks in advance,
Regards, Tore Kleppe
That seems like two unrelated and simple errors.
First off, you need to make that pointer static. Things then work.
Second, using Rcpp Module with inline is no
longer the easiest way around, and we generally recommend using a package -- or Rcpp Attributes as I do below.
Correct code, including explicit messaging to stdout in the constructor:
#include <Rcpp.h>
using namespace Rcpp;
class test;
static test* glob = NULL; //global pointer
class test{
private:
double foo;
public:
test(double foo_) : foo(foo_) {
Rcpp::Rcout << "Seeing foo_ of " << foo_ << " in ctor\n";
glob=this; // the line causes segfault
};
double get_foo(){return foo;};
};
RCPP_MODULE(test){
class_<test>("test")
.constructor<double>()
.property("foo",&test::get_foo)
;
}
Then simple use from the command-line (using littler; R or Rscript are equivalent):
$ r -lRcpp -e 'sourceCpp("/tmp/tore.cpp"); tt <- new(test, 1.23); print(tt$foo)'
Seeing foo_ of 1.23 in ctor
[1] 1.23
$
Note how we can skip all the Module instantiation etc.
I am wondering if there is a Rcpp way to convert an element or iterator of const CharacterVector& to std::string. If I try the following code
void as(const CharacterVector& src) {
std::string glue;
for(int i = 0;i < src.size();i++) {
glue.assign(src[i]);
}
}
a compiler-time error will occurred:
no known conversion for argument 1 from ‘const type {aka SEXPREC* const}’ to ‘const char*’
So far, I use C API to do the conversion:
glue.assign(CHAR(STRING_ELT(src.asSexp(), i)));
My Rcpp version is 0.10.2.
By the way, I do know there is a Rcpp::as.
glue.assign(Rcpp::as<std::string>(src[i]));
the above code will produce a runtime-error:
Error: expecting a string
On the otherhand, the following code run correctly:
typedef std::vector< std::string > StrVec;
StrVec glue( Rcpp::as<StrVec>(src) );
However, I do not want to create a temporal long vector of string in my case.
Thanks for answering.
I am confused as that what you want -- a CharacterVector is a vector of character strings (as in R) so you can only map it to std::vector<std::string> >. Here is a very simple, very manual example (and I thought we had auto-converters for this, but maybe not. Or no more.
#include <Rcpp.h>
// [[Rcpp::export]]
std::vector<std::string> ex(Rcpp::CharacterVector f) {
std::vector<std::string> s(f.size());
for (int i=0; i<f.size(); i++) {
s[i] = std::string(f[i]);
}
return(s);
}
And here it is at work:
R> sourceCpp("/tmp/strings.cpp")
R> ex(c("The","brown","fox"))
[1] "The" "brown" "fox"
R>
In Rcpp 0.12.7, I can use Rcpp::as<std::vector<std::string> >. The following function returns the second element of the test array:
std::string test() {
Rcpp::CharacterVector test = Rcpp::CharacterVector::create("a", "z");
std::vector<std::string> test_string = Rcpp::as<std::vector<std::string> >(test);
return test_string[1];
}