[Rcpp-devel] RcppSexp again
Dirk Eddelbuettel
edd at debian.org
Wed Dec 16 05:25:02 CET 2009
I think I am getting my head wrapped around this. I want a super-simple class
as 'data passthrough' -- C++ types in from SEXPs we get from R, and C++ types
out via SEXPs we send to R. Here is a basic implementation supporting just a
'double'.
-----------------------------------------------------------------------------
#ifndef RcppSexp_h
#define RcppSexp_h
#include <RcppCommon.h>
class RcppSexp {
public:
RcppSexp(SEXP sexp, int numprot=0) : m_sexp(sexp), m_nprot(numprot) {}
RcppSexp() : m_sexp(R_NilValue), m_nprot(0) {}
RcppSexp(const double & d) {
m_sexp = PROTECT(Rf_allocVector(REALSXP, 1));
m_nprot++;
REAL(m_sexp)[0] = d;
}
~RcppSexp() {
UNPROTECT(m_nprot);
}
double asDouble() {
if (Rf_length(m_sexp) != 1) {
throw std::range_error("RcppSexp::asDouble expects single value");
}
if (!Rf_isNumeric(m_sexp)) {
throw std::range_error("RcppSexp::asDouble expect numeric type");
}
if (Rf_isInteger(m_sexp)) {
return (double)INTEGER(m_sexp)[0];
} else if (Rf_isReal(m_sexp)) {
return REAL(m_sexp)[0];
} else {
throw std::range_error("RcppSexp::asDouble invalid type");
}
return 0; // never gets here
}
SEXP asSexp() {
return m_sexp;
}
private:
SEXP m_sexp;
int m_nprot;
};
#endif
-----------------------------------------------------------------------------
which, thanks to Oleg's inline and my adaptation thereof, can be used via
-----------------------------------------------------------------------------
#!/usr/bin/r
suppressMessages(library(Rcpp))
foo <- '
double d = RcppSexp(x).asDouble();
std::cout << "d is " << d << std::endl;
'
funx <- cfunction(signature(x="numeric"), foo, Rcpp=TRUE, verbose=FALSE)
funx(x=2.123)
funx(x=2)
#funx(x='2') ## throws as expected
#funx(x=2:3) ## throws as expected
foo <- '
double d = RcppSexp(x).asDouble();
std::cout << "Returning twice the value of " << d << std::endl;
return(RcppSexp( 2*d ).asSexp());
'
funx <- cfunction(signature(x="numeric"), foo, Rcpp=TRUE, verbose=FALSE)
print(funx(x=2.123))
-----------------------------------------------------------------------------
The last example is particularly nice. One line to go from a SEXP (with
signature 'numeric' as per the argument to cfunction() ) to a C++ double,
and the same on the way out: create an RcppSexp and return it as a plain
SEXP:
-----------------------------------------------------------------------------
edd at ron:~/svn/rcpp$ pkg/inst/examples/RcppInline/RcppSexpTests.r
d is 2.123
d is 2
Returning twice the value of 2.123
[1] 4.246
edd at ron:~/svn/rcpp$
-----------------------------------------------------------------------------
Should work similarly for your vectors of strings of whatever that original
example was.
Dirk
--
Three out of two people have difficulties with fractions.
More information about the Rcpp-devel
mailing list