[Rd] Assignment operator and deep copy for calling C functions

Martyn Plummer plummerm at iarc.fr
Thu Apr 7 10:48:37 CEST 2016


This is discussed in the "Writing R Extensions" manual section 5.9.10:
Named objects and copying.

.Call does not copy its arguments and it is not safe to modify them, as
you have found, since multiple symbols may refer to the same object. If
you are going to modify an argument to .Call you should take a deep
copy with "duplicate" first, and your function should return the
modified copy.

It is probably also worth mentioning Rcpp, which provides a friendlier
interface to R than the C API. In Rcpp you use clone() to force a deep
copy.

Martyn  


On Tue, 2016-04-05 at 15:38 +0000, Thorsten R wrote:
> Hi All,
> 
> i have a problem in understanding what the assignment operator '<-
> '  really is doing.
> If i create two numeric arrays in R and copy one into the other with
> '<-' and
> afterwards change one array by calling a C function, both arrays are
> changed!
> 
> The problem I am facing can easily be seen in the following example:
> (The following R code and the C function is attached and the C
> function can be compiled with R CMD SHLIB test.c.)
> 
> First include the c function:
>     dyn.load("test.so")
> 
> Let's start with 2 arrays:
>     a  <- rep(0, 5)
>     b  <- rep(1, 5)
> 
> Now print the memory addresses:
>     print(sprintf("a: %s    b: %s", tracemem(a), tracemem(b) ))
>     [1] "a: <0x29d34e0>    b: <0x29946e0>"
> 
> oky, they are different! Now copy a into b and print again the
> addresses:
>     b <- a
>     print(sprintf("a: %s    b: %s", tracemem(a), tracemem(b) ))
>     [1] "a: <0x29d34e0>    b: <0x29d34e0>"
> 
> Ugh they are the same. If I now call my C function, which writes
> 0,1,2,3,4 into an array of 5 doubles,
> of course 'both' arrays are changed:
>     .Call("test", b)
>     print( cbind(a,b) )
>          a b
>     [1,] 0 0
>     [2,] 1 1
>     [3,] 2 2
>     [4,] 3 3
>     [5,] 4 4
> 
> 
> If i just change one element of b instead of calling the c function,
> then a full copy of b is made:
>     a <- rep(0, 5)
>     b <- rep(1, 5)
>     print(sprintf("a: %s    b: %s", tracemem(a), tracemem(b) ))
>     [1] "a: <0x2994b58>    b: <0x2912ff8>"
> 
>     b <- a
>     print(sprintf("a: %s    b: %s", tracemem(a), tracemem(b) ))
>     [1] "a: <0x2994b58>    b: <0x2994b58>"
> 
>     b[1] <- 5
>     print(sprintf("a: %s    b: %s", tracemem(a), tracemem(b) ))
>     "a: <0x2994b58>    b: <0x29134d8>"
> 
>     print( cbind(a,b) )
>          a b
>     [1,] 0 5
>     [2,] 0 0
>     [3,] 0 0
>     [4,] 0 0
>     [5,] 0 0
> 
> 
> So what is happening here? What is the 'right' way to ensure a deep
> copy before using Call?
> I am currently using a for loop and copy every single element.
> 
> Thanks!
> 
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel-----------------------------------------------------------------------
This message and its attachments are strictly confidenti...{{dropped:8}}



More information about the R-devel mailing list