[Rcpp-devel] [Rd] must .Call C functions return SEXP?

Dominick Samperi djsamperi at gmail.com
Fri Oct 29 06:37:14 CEST 2010


On Thu, Oct 28, 2010 at 6:04 PM, Douglas Bates <bates at stat.wisc.edu> wrote:

> On Thu, Oct 28, 2010 at 1:44 PM, Dominick Samperi <djsamperi at gmail.com>
> wrote:
> > See comments on Rcpp below.
> >
> > On Thu, Oct 28, 2010 at 11:28 AM, William Dunlap <wdunlap at tibco.com>
> wrote:
> >>
> >> > -----Original Message-----
> >> > From: r-devel-bounces at r-project.org
> >> > [mailto:r-devel-bounces at r-project.org] On Behalf Of Andrew Piskorski
> >> > Sent: Thursday, October 28, 2010 6:48 AM
> >> > To: Simon Urbanek
> >> > Cc: r-devel at r-project.org
> >> > Subject: Re: [Rd] must .Call C functions return SEXP?
> >> >
> >> > On Thu, Oct 28, 2010 at 12:15:56AM -0400, Simon Urbanek wrote:
> >> >
> >> > > > Reason I ask, is I've written some R code which allocates two long
> >> > > > lists, and then calls a C function with .Call.  My C code
> >> > writes to
> >> > > > those two pre-allocated lists,
> >> >
> >> > > That's bad! All arguments are essentially read-only so you should
> >> > > never write into them!
> >> >
> >> > I don't see how.  (So, what am I missing?)  The R docs themselves
> >> > state that the main point of using .Call rather than .C is that .Call
> >> > does not do any extra copying and gives one direct access to the R
> >> > objects.  (This is indeed very useful, e.g. to reorder a large matrix
> >> > in seconds rather than hours.)
> >> >
> >> > I could allocate the two lists in my C code, but so far it was more
> >> > convenient to so in R.  What possible difference in behavior can there
> >> > be between the two approaches?
> >>
> >> Here is an example of how you break the rule that R-language functions
> >> do not change their arguments if you use .Call in the way that you
> >> describe.  The C code is in alter_argument.c:
> >>
> >> #include <R.h>
> >> #include <Rinternals.h>
> >>
> >> SEXP alter_argument(SEXP arg)
> >> {
> >>    SEXP dim ;
> >>    PROTECT(dim = allocVector(INTSXP, 2));
> >>    INTEGER(dim)[0] = 1 ;
> >>    INTEGER(dim)[1] = LENGTH(arg) ;
> >>    setAttrib(arg, R_DimSymbol, dim);
> >>    UNPROTECT(1) ;
> >>    return dim ;
> >> }
> >>
> >> Make a shared library out of this.  E.g., on Linux do
> >>    R CMD SHLIB -o Ralter_argument.so alter_argument.so
> >> and load it into R with
> >>    dyn.open("./Ralter_argument.so")
> >> (Or, on any platform, put it into a package along with
> >> the following R code and build it.)
> >>
> >> The associated R code is
> >>     myDim <- function(v).Call("alter_argument", v)
> >>     f <- function(z) myDim(z)[2]
> >> Now try using it:
> >>     > myData <- 6:10
> >>     > myData
> >>     [1]  6  7  8  9 10
> >>     > f(myData)
> >>     [1] 5
> >>     > myData
> >>          [,1] [,2] [,3] [,4] [,5]
> >>     [1,]    6    7    8    9   10
> >> The argument to f was changed!  This should never happen in R.
> >>
> >> If you are very careful you might be able ensure that
> >> no part of the argument to be altered can come from
> >> outside the function calling .Call().  It can be tricky
> >> to ensure that, especially when the argument is more complicated
> >> than an atomic vector.
> >>
> >> "If you live outside the law you must be honest" - Bob Dylan.
> >
> > This thread seems to suggest (following Bob Dylan) that one needs
> > to be very careful when using C/C++ to modify R's memory
> > directly, because you may modify other R variables that point
> > to the same memory (due to R's copy-by-value semantics and
> > optimizations).
> >
> > What are the implications for the Rcpp package where R
> > objects are exposed to the C++ side in precisely this way,
> > permitting unrestricted modifications? (In the original
> > or "classic" version of this package direct writes to R's
> > memory were done only for performance reasons.)
> >
> > Seems like extra precautions need to be taken to
> > avoid the aliasing problem.
>
> The current Rcpp facilities has the same benefits and dangers as the C
> macros used in .Call.  You get access to the memory of the R object
> passed as an argument, saving a copy step.  You shouldn't modify that
> memory.  If you do, bad things can happen and they will be your fault.
>  If you want to get a read-write copy you clone the argument (in Rcpp
> terminology).
>
> To Bill:  I seem to remember the Dylan quote as "To live outside the
> law you must be honest."
>

And There are No Truths Outside the Gates of Eden.

Cool, a Dylan thread...
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20101029/28eebbc0/attachment-0001.htm>


More information about the Rcpp-devel mailing list