[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