[Rcpp-devel] RcppSexp again

Romain François francoisromain at free.fr
Wed Dec 16 08:32:57 CET 2009


You are essentially going to end up with something similar to Simon's 
java REXP class. 
http://www.rforge.net/org/docs/index.html?org/rosuda/REngine/REXP.html

I'm not sure PROTECT/UNPROTECT is the best solution. It works fine when 
you nicely keep things balanced, but that's a pain and not very 
C++-like. I have not experimented it, but I think we should play with : 
R_PreserveObject/R_ReleaseObject which AFAICS keep things protected from 
GC without relying on the PROTECT stack.

=== (From src/main/memory.c)

/* This code keeps a list of objects which are not assigned to variables
    but which are required to persist across garbage collections.  The
    objects are registered with R_PreserveObject and deregistered with
    R_ReleaseObject. */

void R_PreserveObject(SEXP object)
{
     R_PreciousList = CONS(object, R_PreciousList);
}

void R_ReleaseObject(SEXP object)
{
     R_PreciousList =  RecursiveRelease(object, R_PreciousList);
}

Romain

On 12/16/2009 05:25 AM, Dirk Eddelbuettel wrote:
>
> 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


-- 
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30
http://romainfrancois.blog.free.fr
|- http://tr.im/HlX9 : new package : bibtex
|- http://tr.im/Gq7i : ohloh
`- http://tr.im/FtUu : new package : highlight



More information about the Rcpp-devel mailing list